Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 15494 | Accepted: 4100 |
Description
In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
Input
The first line contains a single integer T, the number of test cases. And followed T cases.
The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.
The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.
Output
The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.
Sample Input
1 3 3 1 2 2 3 3 1
Sample Output
Yes
Source
POJ Monthly--2006.02.26,zgl & twb
题目意思:
给一n个点、m条边的有向图,问是否随意选两个点u和v,是否能从u到达v或者从v到达u。
思路:
如果弱连通分量有多个,那么肯定是不可到达的,所以用并查集处理一下。
如果弱连通分量有多个,那么肯定是不可到达的,所以用并查集处理一下。
强连通分量内部随意两个点是互相到达的,不互相到达的点在强连通分量之间,所以先用tarjan强连通分量缩点,若入度为0的个数>=2||出度为0的个数>=2那么也是不可到达的。
各种条件判断一下即可。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 #include <queue> 7 #include <cmath> 8 #include <set> 9 #include <stack> 10 using namespace std; 11 12 #define N 1005 13 14 int max(int x,int y){return x>y?x:y;} 15 int min(int x,int y){return x<y?x:y;} 16 int abs(int x,int y){return x<0?-x:x;} 17 18 int n, m; 19 bool in[N]; 20 int suo[N]; 21 int cnt; 22 vector<int>ve[N]; 23 int dfn[N], low[N], Time; 24 stack<int>st; 25 int father[N]; 26 27 int findroot(int u){ 28 if(father[u]!=u) father[u]=findroot(father[u]); 29 return father[u]; 30 } 31 32 void tarjan(int u){ 33 dfn[u]=low[u]=Time++; 34 st.push(u);in[u]=true; 35 int i, j, k; 36 for(i=0;i<ve[u].size();i++){ 37 int v=ve[u][i]; 38 if(dfn[v]==-1){ 39 tarjan(v); 40 low[u]=min(low[u],low[v]); 41 } 42 else if(in[v]) low[u]=min(low[u],dfn[v]); 43 } 44 if(dfn[u]==low[u]){ 45 while(1){ 46 int x=st.top(); 47 suo[x]=cnt; 48 in[x]=false; 49 st.pop(); 50 if(x==u||st.empty()) break; 51 } 52 cnt++; 53 } 54 } 55 56 main() 57 { 58 int i, j, k, u, v; 59 int t; 60 cin>>t; 61 62 while(t--){ 63 scanf("%d %d",&n,&m); 64 for(i=0;i<=n;i++) ve[i].clear(); 65 for(i=0;i<m;i++){ 66 scanf("%d %d",&u,&v); 67 ve[u].push_back(v); 68 } 69 Time=cnt=1; 70 memset(dfn,-1,sizeof(dfn)); 71 while(!st.empty()) st.pop(); 72 memset(in,false,sizeof(in)); 73 for(i=1;i<=n;i++){ 74 if(dfn[i]==-1){ 75 tarjan(i); 76 } 77 } 78 int inn[N], out[N]; 79 memset(inn,0,sizeof(inn)); 80 memset(out,0,sizeof(out)); 81 for(i=1;i<=n;i++) father[i]=i; 82 for(i=1;i<=n;i++){ 83 for(j=0;j<ve[i].size();j++){ 84 int u=suo[i], v=suo[ve[i][j]]; 85 if(u!=v){ 86 father[findroot(v)]=findroot(u); 87 inn[v]++; 88 out[u]++; 89 } 90 } 91 } 92 93 int num=0; 94 for(i=1;i<cnt;i++){ 95 if(father[i]==i) num++; 96 } 97 if(num>1) { 98 printf("No ");continue; 99 } 100 101 int n1, n2; 102 n1=n2=0; 103 for(i=1;i<cnt;i++){ 104 if(!inn[i]) n1++; 105 if(!out[i]) n2++; 106 } 107 if(n1>1||n2>1) printf("No "); 108 else printf("Yes "); 109 } 110 }