Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 16486 | Accepted: 4386 |
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
题意:
有一张有向图,然后问对于任意的2个点,是否存在x可以到达y,或者y能够到达x。
思路:
可以先强连通缩点,这样就没有环的情况。然后这样就是一张新的图。也就是相当于在新的图中判断任意2个点能否存在一条路径。这可以用topo排序来解决。如果存在2个点,他们的入度为0,说明这2个点是不能相互到达的。
/* * Author: sweat123 * Created Time: 2016/6/25 12:33:09 * File Name: main.cpp */ #include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<string> #include<vector> #include<cstdio> #include<time.h> #include<cstring> #include<iostream> #include<algorithm> #define INF 1<<30 #define MOD 1000000007 #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pi acos(-1.0) using namespace std; const int MAXN = 20000; struct node{ int from; int to; int next; }edge[MAXN*1000]; int pre[MAXN],vis[MAXN],dfn[MAXN],low[MAXN],n,m,ind; int f[MAXN],num,k; stack<int>s; void add(int x,int y){ edge[ind].from = x; edge[ind].to = y; edge[ind].next = pre[x]; pre[x] = ind ++; } void dfs(int rt){ vis[rt] = 1; dfn[rt] = low[rt] = ++k; s.push(rt); for(int i = pre[rt]; i != -1; i = edge[i].next){ int t = edge[i].to; if(!dfn[t]){ dfs(t); low[rt] = min(low[rt],low[t]); } else if(vis[t]){ low[rt] = min(low[rt],dfn[t]); } } if(low[rt] == dfn[rt]){ ++ num; while(!s.empty()){ int tp = s.top(); s.pop(); vis[tp] = 0; f[tp] = num; if(tp == rt)break; } } } int x[MAXN],y[MAXN],ans,in[MAXN]; int ok(){ queue<int>q; for(int i = 1; i <= num; i++){ if(in[i] == 0){ q.push(i); } } if(q.size() > 1)return 0; while(!q.empty()){ int tp = q.front(); q.pop(); for(int i = pre[tp]; i != -1; i = edge[i].next){ int t = edge[i].to; in[t] --; if(in[t] == 0){ q.push(t); } } if(q.size() > 1)return 0; } return 1; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); ind = 0; while(!s.empty())s.pop(); memset(pre,-1,sizeof(pre)); for(int i = 1; i <= m; i++){ scanf("%d%d",&x[i],&y[i]); add(x[i],y[i]); } k = 0; num = 0; memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); for(int i = 1; i <= n; i++){ if(!dfn[i])dfs(i); } memset(pre,-1,sizeof(pre)); memset(in,0,sizeof(in)); int ret = ind; for(int i = 0; i < ret; i++){ int u = f[edge[i].from]; int v = f[edge[i].to]; if(u != v){ add(u,v); in[v] ++; } } if(ok()){ printf("Yes\n"); } else{ printf("No\n"); } } return 0; }