[强连通分量] POJ 2762 Going from u to v or from v to u?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[强连通分量] POJ 2762 Going from u to v or from v to u?相关的知识,希望对你有一定的参考价值。
Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 17089 | Accepted: 4590 |
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
Source
POJ Monthly--2006.02.26,zgl & twb
原题大意:T组数据,每组数据输入点的个数n和边的个数m,接下来m行输入a,b,表示从a到b有一条有向边,问是否每两个点之间存在通路(即a->b和b->a任意存在一条即可)。
解题思路:首先这是一个连通问题,我们要看是否连通,为了让算法变得简单,可以将原图中所有强连通分量看作一个点,于是要先缩点。
于是,先将整个图用tarjian标记,然后缩点成DAG图(有向无环图,简称G图)。
接下来我们考虑这个G图,想一下首先,如果其中一个点(即原图中一个强连通分量)的出度>1,那么很显然,它所指向的另外几个点互不相通。
那么解法就来了:
假设G图中入度为0的点为起点,它所指向的点为子节点,那么每个点只能有一个子节点。
也就是说,这个G图中各个点链接像单向链表的时候满足题意。
于是我们可以简单模拟(也就是用入度和出度和它们的方向暴力一遍),也可以改一下拓扑排序,判断是否为单链。
最后输出答案就可以了。
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 using namespace std; 5 queue<int> q; 6 struct list 7 { 8 int v; 9 list *next; 10 }; 11 list *head[10010],*rear[10010],*map_head[10010],*map_rear[10010]; 12 int stack[10010],s[10010],dfn[10010],low[10010],indegree[10010]; 13 bool instack[10010]; 14 int top,cnt,times; 15 void tarjian(int v) 16 { 17 dfn[v]=low[v]=++times; 18 stack[top++]=v; 19 instack[v]=true; 20 for(list *p=head[v];p!=NULL;p=p->next) 21 if(!dfn[p->v]) 22 { 23 tarjian(p->v); 24 if(low[p->v]<low[v]) low[v]=low[p->v]; 25 } else if(low[p->v]<low[v]&&instack[p->v]) low[v]=low[p->v]; 26 if(dfn[v]==low[v]) 27 { 28 ++cnt; 29 do 30 { 31 v=stack[--top]; 32 instack[v]=false; 33 s[v]=cnt; 34 }while(dfn[v]!=low[v]); 35 } 36 return; 37 } 38 bool topsort() 39 { 40 int count=0,i; 41 while(!q.empty()) q.pop(); 42 for(i=1;i<=cnt;++i) 43 { 44 if(!indegree[i]) 45 { 46 ++count; 47 q.push(i); 48 } 49 } 50 if(count>1) return false; 51 while(!q.empty()) 52 { 53 int u=q.front(); 54 q.pop(); 55 count=0; 56 for(list *p=map_head[u];p!=NULL;p=p->next) 57 { 58 --indegree[p->v]; 59 if(!indegree[p->v]) 60 { 61 ++count; 62 q.push(p->v); 63 } 64 } 65 if(count>1) return false; 66 } 67 return true; 68 } 69 int main() 70 { 71 int T,n,m,i,u,v,a,b,num; 72 scanf("%d",&T); 73 while(T--) 74 { 75 memset(head,0,sizeof(head)); 76 memset(rear,0,sizeof(rear)); 77 scanf("%d%d",&n,&m); 78 for(i=0;i<m;++i) 79 { 80 scanf("%d%d",&u,&v); 81 if(rear[u]!=NULL) 82 { 83 rear[u]->next=new list; 84 rear[u]=rear[u]->next; 85 }else head[u]=rear[u]=new list; 86 rear[u]->v=v; 87 rear[u]->next=NULL; 88 } 89 top=times=cnt=0; 90 memset(dfn,0,sizeof(dfn)); 91 memset(low,0,sizeof(low)); 92 memset(stack,0,sizeof(stack)); 93 memset(instack,false,sizeof(instack)); 94 memset(s,0,sizeof(s)); 95 for(i=1;i<=n;++i) if(!dfn[i]) tarjian(i); 96 memset(map_head,0,sizeof(map_head)); 97 memset(map_rear,0,sizeof(map_rear)); 98 memset(indegree,0,sizeof(indegree)); 99 for(i=1;i<=n;++i) 100 for(list *p=head[i];p!=NULL;p=p->next) 101 if(s[i]!=s[p->v]) 102 { 103 ++indegree[s[p->v]]; 104 if(map_rear[s[i]]!=NULL) 105 { 106 map_rear[s[i]]->next=new list; 107 map_rear[s[i]]=map_rear[s[i]]->next; 108 } else map_head[s[i]]=map_rear[s[i]]=new list; 109 map_rear[s[i]]->v=s[p->v]; 110 map_rear[s[i]]->next=NULL; 111 } 112 if(topsort()) printf("Yes\n"); 113 else printf("No\n"); 114 } 115 return 0; 116 }
以上是关于[强连通分量] POJ 2762 Going from u to v or from v to u?的主要内容,如果未能解决你的问题,请参考以下文章
POJ2762 Going from u to v or from v to u? 强连通+缩点
POJ - 2762 Going from u to v or from v to u? (强连通缩点+判断单向连通)
POJ 2762 Going from u to v or from v to u? (判断弱连通)
POJ 2762--Going from u to v or from v to u?scc缩点新建图 && 推断是否是弱连通图