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

     

  • 相关阅读:
    leetcode Remove Linked List Elements
    leetcode Word Pattern
    leetcode Isomorphic Strings
    leetcode Valid Parentheses
    leetcode Remove Nth Node From End of List
    leetcode Contains Duplicate II
    leetcode Rectangle Area
    leetcode Length of Last Word
    leetcode Valid Sudoku
    leetcode Reverse Bits
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/3265690.html
Copyright © 2011-2022 走看看