zoukankan      html  css  js  c++  java
  • HDU4674 Trip Advisor

    Problem Description
    There is a strange country somewhere which its transportation network was built following some weird rules: Consider the transportation network as a connected undirected graph G with N nodes and M edges(nodes indicate cities,and people can travel from cities to cities by roads connecting them),the condition that every node in G is in at most one simple cycle holds.
    One day Q people of the country want to make a travel, i_th people is located at city Ui, wants to move to city Vi(Ui can be equal to Vi),and he especially loves city Pi,so he wonders if there is a path that:

    1. starts at Ui;
    2. ends at Vi;
    3. for every pair of adjacent cities in path,there is a road connecting them.
    4. visits every city at most once.
    5. visits city Pi;

    As a trip advisor,your task is to tell everybody whether there is a path satsifying all his requirements.
     


    Input
    The input contains several test cases, terminated by EOF. Most of test cases are rather small.
    Each testcase contains M + Q + 2 lines. first line contains two integers N, M (1 <= N <= 100000, 1 <= M <= 150000), the number of cities and roads; next M lines each contains two integer b, e indicates that there is a bidirectional-road connecting city b and city e;next line an integer Q (1 ≤ Q ≤ 100000) indicating number of people in that country that want to make a travel, next Q lines each contains three integers Ui, Vi, Pi, denotes the query as we mentioned above.
     


    Output
    For each test case output Q lines, for i-th query, if there exists such path, output one line "Yes" without quotes, otherwise output one line "No" without quotes.
     


    Sample Input
    6 7 1 2 1 2 3 4 2 4 5 6 5 6 4 5 5 1 6 3 1 6 4 1 2 5 2 2 2 2 2 3
     


    Sample Output
    No Yes No Yes No
     


    Source
     
      1 //#pragma comment(linker, "/STACK:65536000")
      2 #include <iostream>
      3 #include <stdio.h>
      4 #include <string.h>
      5 #include <vector>
      6 #include <map>
      7 #include <math.h>
      8 #include <queue>
      9 #include <set>
     10 #include <algorithm>
     11 #define clr(a,b) memset(a,b,sizeof(a))
     12 #define mpr(a,b) make_pair(a,b)
     13 #define ll long long
     14 #define eps 1e-6
     15 using namespace std;
     16 
     17 const int N=100005,M=300005;
     18 
     19 /*
     20 * HDU4674
     21 * 一个无向图,每个点最多只属于一个简单环,询问从a到b的简单路径能不能路过c
     22 * 离线处理,先缩点,假设缩点完后a为A,b为B,c为C
     23 * 对每个询问分别求出lca(A,B),lca(A,C),lca(B,C)
     24 * 还要判断两个点求lca的时候,对lca的那个点,进出的联通块分别是哪个点,这个
     25 * 在做完一边lca后再dfs一边就好了
     26 * come记录从父亲节点进入这个联通块的是哪个点
     27 * out数组在dfs中记录当前祖先的状态
     28 * gra数组用来缩点建图,first保存连到下一个联通块的编号,
     29                second保存从该联通块该边连出去的是哪个点
     30 * qu数组用来lca询问
     31 * tlca记录每个lca的值
     32 * pt表示两个点连到lca的时候,进出lca那个联通块的点,-1说明就在lca上
     33 */
     34 int n,m,q,eid,id,now,top;
     35 int head[N],ed[M],nxt[M];
     36 int dfn[N],low[N],gid[N];
     37 int sta[N],block[N];
     38 vector<pair<int,int> >gra[N],qu[N];
     39 int f[N],vis[N],come[N],out[N],fa[N];
     40 int tlca[3*N],pt[3*N][2];
     41 int aa[N],bb[N],cc[N];
     42 
     43 int findfa(int s){return s==fa[s]?s:fa[s]=findfa(fa[s]);}
     44 
     45 void addedge(int s,int e){
     46      ed[eid]=e;nxt[eid]=head[s];head[s]=eid++;
     47 }
     48 
     49 void tarjan(int s,int f,int b){
     50      dfn[s]=low[s]=++now;
     51      sta[top++]=s;block[s]=b;
     52      for(int i=head[s];~i;i=nxt[i]){
     53           int e=ed[i];
     54           if(i==f||i==(f^1))continue;
     55           if(!dfn[e]){
     56                tarjan(e,i,b);
     57                low[s]=min(low[s],low[e]);
     58           }else
     59                low[s]=min(low[s],dfn[e]);
     60      }
     61      if(low[s]==dfn[s]){
     62           id++;
     63           while(top){
     64                int k=sta[--top];
     65                gid[k]=id;
     66                if(k==s)return ;
     67           }
     68      }
     69 }
     70 
     71 void lca(int s,int f){
     72      fa[s]=s;
     73      for(int i=0;i<(int)gra[s].size();i++){
     74           int e=gra[s][i].first;
     75           if(e==f)continue;
     76           lca(e,s);
     77           fa[findfa(e)]=s;
     78      }
     79      vis[s]=1;
     80      for(int i=0;i<(int)qu[s].size();i++){
     81           int e=qu[s][i].first,d=qu[s][i].second;
     82           if(vis[e])tlca[d]=findfa(e);
     83      }
     84 }
     85 
     86 void dfs(int s,int f){
     87      for(int i=0;i<(int)qu[s].size();i++){
     88           int d=qu[s][i].second;
     89           int k=(tlca[d]==s)?-1:out[tlca[d]];
     90           if(~pt[d][0])pt[d][1]=k;
     91           else pt[d][0]=k;
     92      }
     93      for(int i=0;i<(int)gra[s].size();i++){
     94           int e=gra[s][i].first,g=gra[s][i].second;
     95           if(e==f){
     96                come[s]=g;continue;
     97           }
     98           out[s]=g;
     99           dfs(e,s);
    100      }
    101 }
    102 
    103 int main(){
    104 //     freopen("/home/axorb/in","r",stdin);
    105      while(~scanf("%d%d",&n,&m)){
    106           eid=0;clr(head,-1);
    107           for(int i=0;i<m;i++){
    108                int a,b;scanf("%d%d",&a,&b);
    109                addedge(a,b);addedge(b,a);
    110           }
    111           id=now=top=0;
    112           for(int i=1;i<=n;i++)dfn[i]=0;
    113           int cnt=0;
    114           for(int i=1;i<=n;i++)
    115                if(!dfn[i])tarjan(i,-1,++cnt);
    116           for(int i=1;i<=id;i++){
    117                gra[i].clear();qu[i].clear();
    118           }
    119           for(int i=1;i<=n;i++)
    120                for(int j=head[i];~j;j=nxt[j]){
    121                     int s=gid[i],e=gid[ed[j]];
    122                     if(s!=e)gra[s].push_back(mpr(e,i));
    123                }
    124           clr(f,0);
    125           scanf("%d",&q);
    126           for(int i=0;i<q;i++){
    127                int a,b,c;scanf("%d%d%d",&a,&b,&c);
    128                //如果3个点不能到达,则答案肯定否定
    129                if(block[a]!=block[b]){f[i]=1;continue;}
    130                if(block[b]!=block[c]){f[i]=1;continue;}
    131                if(block[a]!=block[c]){f[i]=1;continue;}
    132                //如果起点和终点相同,那个路过的点也必须相同
    133                if(a==b&&a!=c){f[i]=1;continue;}
    134                int s=gid[a],e=gid[b],k=gid[c];
    135                qu[s].push_back(mpr(e,i*3));
    136                qu[e].push_back(mpr(s,i*3));
    137                qu[s].push_back(mpr(k,i*3+1));
    138                qu[k].push_back(mpr(s,i*3+1));
    139                qu[e].push_back(mpr(k,i*3+2));
    140                qu[k].push_back(mpr(e,i*3+2));
    141                aa[i]=a;bb[i]=b;cc[i]=c;
    142           }
    143           for(int i=1;i<=id;i++)vis[i]=0;
    144           for(int i=0;i<q*3;i++)
    145                pt[i][0]=pt[i][1]=-1;
    146           for(int i=1;i<=id;i++)
    147                if(!vis[i]){
    148                     lca(i,-1);
    149                     dfs(i,-1);
    150                }
    151           for(int i=0;i<q;i++){
    152                if(f[i]){
    153                     puts("No");continue;
    154                }
    155                if(gid[aa[i]]==gid[bb[i]]){//如果A=B,那个C必须等于A
    156                     if(gid[cc[i]]==gid[aa[i]])puts("Yes");
    157                     else puts("No");
    158                }
    159                else if(gid[cc[i]]==tlca[i*3]){//如果C是lca(A,B)
    160                     if(pt[i*3][1]==-1){
    161                          //如果AB中有一个等于C,那么当那个点是出口且C不是出口的时候,C就不能到达
    162                          int k=(gid[aa[i]]==gid[cc[i]])?aa[i]:bb[i];
    163                          if(k==pt[i*3][0]&&cc[i]!=k) puts("No");
    164                          else puts("Yes");
    165                     }else{
    166                          //如果AB都不是C,那个当AB进出C的是同一个点且不是C,C就不能到达
    167                          if(pt[i*3][0]==pt[i*3][1]&&cc[i]!=pt[i*3][0]) puts("No");
    168                          else puts("Yes");
    169                     }
    170                }else if(tlca[i*3+1]==gid[cc[i]]&&tlca[i*3+2]==tlca[i*3]){
    171                     //如果C是A的祖先,且lca(A,B)=lca(C,B)
    172                     //那么当父亲到C的点和C连出去到A的点是同一个点且不是C,那个C就不能到达
    173                     int k=(pt[i*3+1][0]==-1)?aa[i]:pt[i*3+1][0];
    174                     if(come[gid[cc[i]]]==k&&k!=cc[i])puts("No");
    175                     else puts("Yes");
    176                }else if(tlca[i*3+2]==gid[cc[i]]&&tlca[i*3+1]==tlca[i*3]){
    177                     //同上
    178                     int k=(pt[i*3+2][0]==-1)?bb[i]:pt[i*3+2][0];
    179                     if(come[gid[cc[i]]]==k&&k!=cc[i])puts("No");
    180                     else puts("Yes");
    181                }else puts("No");
    182           }
    183      }
    184 }
    View Code

     

  • 相关阅读:
    Queue
    List
    面试1
    野指针和空指针
    指针的定义和使用
    多文件编程
    函数声明
    函数样式
    字符串比较
    函数的定义和使用
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/3265690.html
Copyright © 2011-2022 走看看