Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 14564 | Accepted: 3845 |
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/* 题目大意:给你点个数和边个数,告诉你一些单向联通的两点,问这个图中的所有点是否可以任意两点,u、v,可以u到达v或者v到达u,如果可以输出Yes,否则输出No 先求强联通缩点,然后将点进行拓扑排序,如果有分叉,则说明不行,也就是说缩点之后必须是单链。 心得:对着答案终于对出错误来了。 加油!!! 另外,提供三组测试数据 3 3 3 1 2 2 3 3 1 3 3 1 2 2 1 3 1 4 4 1 2 1 3 2 4 3 4 Yes Yes No 过了这三组应该能过 Time:2014-10-5 17:33 */ #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; #define MAX 1010 #define mem(a,b) memset(a,b,sizeof(a)) struct Edge{ int to,next; }edge[MAX<<3],edge1[MAX<<3]; int en,en1; int head[MAX],head1[MAX]; int dfn[MAX],in[MAX],low[MAX],id[MAX],stack[MAX]; bool instack[MAX]; int idx,top,cnt; void Add(int u,int v){ edge[en].to=v; edge[en].next=head[u]; head[u]=en++; } void Add1(int u,int v){ edge1[en1].to=v; edge1[en1].next=head1[u]; head1[u]=en1++; } void Init(){ cnt=en=en1=idx=top=0; mem(dfn,0);mem(low,0); mem(id,0);mem(stack,0); mem(instack,0);mem(in,0); mem(head,-1);mem(head1,-1); } void Tarjan(int u){ dfn[u]=low[u]=++idx; stack[++top]=u;instack[u]=true; int v; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to;//i错写成u if(dfn[v]==0){ Tarjan(v); low[u]=min(low[u],low[v]); }else if(instack[v]){ low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]){ cnt++; do{ v=stack[top--]; id[v]=cnt; instack[v]=false; }while(u!=v); } } bool topSort(){ queue<int>q; for(int i=1;i<=cnt;i++){ if(in[i]==0) q.push(i); } if(q.size()>1)return false; while(!q.empty()){ int cur=q.front();q.pop(); for(int i=head1[cur];i!=-1;i=edge1[i].next){ int v=edge1[i].to; in[v]--; if(in[v]==0){ q.push(v); } } if(q.size()>1) return false; } return true; } void solve(){ int T,N,M; scanf("%d",&T); while(T--){ int u,v; Init(); scanf("%d%d",&N,&M); for(int i=0;i<M;i++){ scanf("%d%d",&u,&v); Add(u,v); } for(int i=1;i<=N;i++){ if(!dfn[i])//没被访问过 三处错 Tarjan(i); } if(cnt==1){printf("Yes\n");continue;} for(int i=1;i<=N;i++){ for(int j=head[i];j!=-1;j=edge[j].next){ int v=edge[j].to;//两处错 if(id[i]!=id[v]){ in[id[v]]++; Add1(id[i],id[v]); } } } if(topSort()){ printf("Yes\n"); }else{ printf("No\n"); } } } int main(){ //freopen("poj2762.txt","r",stdin); solve(); return 0; }