Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 14566 | Accepted: 3846 |
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.
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 题目意思:给出一个结点数目为n,边数为m的有向图,若随意选出两个结点x、y,若能从x到y或者(注意,不是而且)y到x,输出Yes,否则输出No。 思路:在强连通里肯定成立,若不成立,肯定在两个强连通分量里面,那么狠容易想到缩点分块了。画了几个图后发现若分块后的图为单链那么肯定成立,若不是单链即有分叉的话那么不成立,自然而然想到拓扑了,每次删除一个入度为0的点,就看一下入度为0的点为多少个,若>1则不成立。 代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 using namespace std; 9 10 #define N 10005 11 12 int low[N], dfn[N], dfn_clock; 13 int instack[N], a[N], in[N]; 14 int n, m; 15 stack<int>st; 16 vector<int>ve[N],out[N]; 17 int ans, num; 18 19 void init(){ 20 int i; 21 for(i=0;i<=n;i++){ 22 ve[i].clear();instack[i]=1; 23 out[i].clear(); 24 } 25 memset(dfn,0,sizeof(dfn)); 26 memset(in,0,sizeof(in)); 27 } 28 29 void tarjan(int u){ 30 int v, i, j; 31 dfn[u]=low[u]=dfn_clock++; 32 st.push(u); 33 for(i=0;i<ve[u].size();i++){ 34 v=ve[u][i]; 35 if(!dfn[v]){ 36 tarjan(v); 37 low[u]=min(low[u],low[v]); 38 } 39 else if(instack[v]){ 40 low[u]=min(low[u],dfn[v]); 41 } 42 } 43 if(low[u]==dfn[u]){ 44 ans++; 45 while(1){ 46 v=st.top();st.pop(); 47 instack[v]=0; 48 a[v]=ans; 49 if(v==u){ 50 break; 51 } 52 } 53 } 54 } 55 56 main() 57 { 58 int i, j, k; 59 int x, y; 60 int t; 61 cin>>t; 62 63 while(t--){ 64 scanf("%d %d",&n,&m); 65 init(); 66 while(m--){ 67 scanf("%d %d",&x,&y); 68 ve[x].push_back(y); 69 } 70 dfn_clock=1;ans=0; 71 for(i=1;i<=n;i++){ 72 if(!dfn[i]) 73 tarjan(i); 74 } 75 for(i=1;i<=n;i++){ 76 for(j=0;j<ve[i].size();j++){ 77 x=ve[i][j]; 78 if(a[x]!=a[i]){ 79 in[a[x]]++; 80 out[a[i]].push_back(a[x]); 81 } 82 } 83 } 84 int aa, f; 85 // printf("%d\n",ans); 86 // for(i=1;i<=n;i++){ 87 // printf("%d ",a[i]); 88 // } 89 // cout<<endl; 90 for(i=1;i<=ans;i++){ 91 aa=0;f=0; 92 for(j=1;j<=ans;j++){ 93 if(!in[j]) aa++; 94 if(!in[j]&&!f){ 95 for(k=0;k<out[j].size();k++){ 96 in[out[j][k]]--; 97 } 98 in[j]=-1;f=1; 99 } 100 101 } 102 103 if(aa>1) break; 104 105 } 106 if(aa<=1) printf("Yes\n"); 107 else printf("No\n"); 108 } 109 }