首页 > 代码库 > [强连通分量] POJ 2762 Going from u to v or from v to u?

[强连通分量] 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. 

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?