您的位置:首页 > 编程语言 > Go语言

poj 2762 Going from u to v or from v to u?(缩点+拓扑排序)

2013-08-14 17:43 489 查看
Going from u to v or from v to u?
Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 12804Accepted: 3311
DescriptionIn 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 oneto 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 pairof rooms is a possible task. Given a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?InputThe 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.OutputThe 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
题意:给出一个有向图,判断该图是否为单向连通图:如果有向图中,对于任意节点v1和v2,至少存在从v1到v2和从v2到v1的路径中的一条,则原图为单向连通图。
思路:先对原图进行缩点。可以证明,若是单向连通图,缩点后形成的图形是一棵树,入度为0的点是这颗树的根,这棵树只能是单链,不能有分叉,因为如果有分叉,则这些分叉之间是不可达的。所以我们缩点后对新图进行拓扑排序,若拓扑排序的过程中,删除一个点和对应的边后,有超过1个点的入度为0,则该图不是单向连通图。
AC代码:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <vector>#include <cmath>#include <cstdlib>#include <map>#define L(rt) (rt<<1)#define R(rt) (rt<<1|1)#define ll long longusing namespace std;const int maxn=1005;const int maxm=6005;const double INF=1000000000;struct node{int v,next;}edge[maxm*2];int G[maxn],NG[maxn],scc[maxn],in[maxn];int low[maxn],dfn[maxn],stack[maxn];bool ins[maxn];int n,m,num,cnt,snum,top;void init(){memset(G,-1,sizeof(G));memset(NG,-1,sizeof(NG));num=0;}void add(int *head,int u,int v){edge[num].v=v;edge[num].next=head[u];head[u]=num++;}void input(){int a,b;scanf("%d%d",&n,&m);while(m--){scanf("%d%d",&a,&b);add(G,a,b);}}void dfs(int u){int x;dfn[u]=low[u]=++cnt;stack[top++]=u;ins[u]=true;for(int i=G[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(!dfn[v]){dfs(v);low[u]=min(low[u],low[v]);}else if(ins[v]) low[u]=min(low[u],dfn[v]);}if(low[u]==dfn[u]){snum++;do{x=stack[--top];ins[x]=false;scc[x]=snum;}while(x!=u);}}void tarjan(){memset(ins,false,sizeof(ins));memset(dfn,0,sizeof(dfn));snum=top=cnt=0;for(int i=1;i<=n;i++)if(!dfn[i]) dfs(i);}bool toposort(){queue<int>Q;for(int u=1;u<=snum;u++)if(!in[u]) Q.push(u);while(!Q.empty()){if(Q.size()>1) return false;int u=Q.front();Q.pop();for(int i=NG[u];i!=-1;i=edge[i].next){int v=edge[i].v;in[v]--;if(!in[v]) Q.push(v);}}return true;}void solve(){memset(in,0,sizeof(in));for(int u=1;u<=n;u++)for(int i=G[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(scc[u]!=scc[v]){add(NG,scc[u],scc[v]);in[scc[v]]++;}}if(toposort()) printf("Yes\n");else printf("No\n");}int main(){int t;scanf("%d",&t);while(t--){init();input();tarjan();solve();}return 0;}
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐