Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 18557 | Accepted: 5000 |
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
题意:有 n 个房间,不同房间之间有单向通道,问是否任意两个房间 A 、B 都可以从 A 到 B 或从 B 到 A。
思路:先用强连通缩点来化简图,然后在图上做拓扑排序,如果排序过程中,出现2个及以上的点入度同时为0时,那么就不满足条件。
代码:#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <stack> #include <cmath> #include <vector> using namespace std; const int N=1001+100; int dfn[N],low[N],belong[N]; bool instack[N]; int head[N]; int in[N],out[N]; int cnt,index,num; vector<int>g[N]; vector<int>e[N]; stack<int>s; int m,n; void init() { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(belong,0,sizeof(belong)); memset(instack,false,sizeof(instack)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); cnt=index=0; for(int i=0;i<=n;i++) { g[i].clear(); e[i].clear(); } while(!s.empty()) s.pop(); } void tarjan(int u) { dfn[u]=low[u]=++index; s.push(u); instack[u]=true; int v; for(int i=0;i<g[u].size();i++) { v=g[u][i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[v],low[u]); } else if(instack[v]) { low[u]=min(dfn[v],low[u]); } } if(dfn[u]==low[u]) { cnt++; do{ v=s.top(); s.pop(); belong[v]=cnt; instack[v]=false; }while(u!=v); } } bool topsort() { queue<int>Q; int count=0; while(!Q.empty())Q.pop(); for(int i=1;i<=cnt;i++) { if(in[i]==0) { count++; Q.push(i); } } if(count>1)return false; while(!Q.empty()) { int u=Q.front(); Q.pop(); count=0; for(int i=0;i<e[u].size();i++) { int v=e[u][i]; in[v]--; if(in[v]==0) { count++; Q.push(v); } } if(count>1)return false; } return true; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(); int i,j; int a,b; for(i=0;i<m;i++) { scanf("%d%d",&a,&b); g[a].push_back(b); } for(i=1;i<=n;i++) { if(!dfn[i]) { tarjan(i); } } for(i=1;i<=n;i++) { for(j=0;j<g[i].size();j++) { int v=g[i][j]; if(belong[v]!=belong[i]) { in[belong[v]]++; out[belong[i]]++; e[belong[i]].push_back(belong[v]); } } } if(topsort())cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }