zoukankan      html  css  js  c++  java
  • [强连通分量] 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

     
    原题大意: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
    ");
    113           else printf("No
    ");
    114        }
    115        return 0;
    116   }
  • 相关阅读:
    自动刷新页面
    超链接<A>链接到某个文档
    JS脚本的对话框
    表最后更新的标识列
    c#对象私有属性在重载Equals中的使用
    一个关于在Fedora下安装jdk的问题
    表格的行转列
    UNION和UNION ALL的区别
    关于使用存储过程的一些好处以及注意事项[转]
    SQL 外链接操作小结
  • 原文地址:https://www.cnblogs.com/fuermowei-sw/p/6143295.html
Copyright © 2011-2022 走看看