zoukankan      html  css  js  c++  java
  • POJ2762 Going from u to v or from v to u?(判定单连通图:强连通分量+缩点+拓扑排序)

    这道题要判断一张有向图是否是单连通图,即图中是否任意两点u和v都存在u到v或v到u的路径。

    方法是,找出图中所有强连通分量,强连通分量上的点肯定也是满足单连通性的,然后对强连通分量进行缩点,缩点后就变成DAG。

    现在问题就变成,如何判断DAG是否是单连通图——用拓扑排序——如果拓扑排序过程中出现1个以上入度为0的点那就不是单连通图,因为有2个入度0的点,那这两个点肯定都无法到达对方。

    另外,注意题目没说给的图是连通的!。。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 #define MAXN 1111
     7 #define MAXM 6666
     8 struct Edge{
     9     int u,v,next;
    10 }edge[MAXM];
    11 int NE,head[MAXN];
    12 void addEdge(int u,int v){
    13     edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u];
    14     head[u]=NE++;
    15 }
    16 
    17 int belong[MAXN],bn,stack[MAXN],top;
    18 bool instack[MAXN];
    19 int dn,dfn[MAXN],low[MAXN];
    20 void dfs(int u){
    21     dfn[u]=low[u]=++dn;
    22     stack[++top]=u; instack[u]=1;
    23     for(int i=head[u]; i!=-1; i=edge[i].next){
    24         int v=edge[i].v;
    25         if(dfn[v]==0){
    26             dfs(v);
    27             low[u]=min(low[u],low[v]);
    28         }else if(instack[v]){
    29             low[u]=min(low[u],dfn[v]);
    30         }
    31     }
    32     if(dfn[u]==low[u]){
    33         int v; ++bn;
    34         do{
    35             v=stack[top--];
    36             belong[v]=bn;
    37             instack[v]=0;
    38         }while(u!=v);
    39     }
    40 }
    41 
    42 int deg[MAXN];
    43 bool toposort(){
    44     queue<int> que;
    45     for(int i=1; i<=bn; ++i){
    46         if(deg[i]==0) que.push(i);
    47     }
    48     if(que.size()>1) return 0;
    49     while(!que.empty()){
    50         int u=que.front(); que.pop();
    51         for(int i=head[u]; i!=-1; i=edge[i].next){
    52             int v=edge[i].v;
    53             if(--deg[v]==0) que.push(v);
    54         }
    55         if(que.size()>1) return 0;
    56     }
    57     return 1;
    58 }
    59 int main(){
    60     int t,n,m,a,b;
    61     scanf("%d",&t);
    62     while(t--){
    63         NE=0;
    64         memset(head,-1,sizeof(head));
    65         scanf("%d%d",&n,&m);
    66         while(m--){
    67             scanf("%d%d",&a,&b);
    68             addEdge(a,b);
    69         }
    70 
    71         top=bn=dn=0;
    72         memset(instack,0,sizeof(instack));
    73         memset(dfn,0,sizeof(dfn));
    74         for(int i=1; i<=n; ++i){
    75             if(dfn[i]==0) dfs(i);
    76         }
    77 
    78         int tmp=NE; NE=0;
    79         memset(head,-1,sizeof(head));
    80         memset(deg,0,sizeof(deg));
    81         for(int i=0; i<tmp; ++i){
    82             int u=belong[edge[i].u],v=belong[edge[i].v];
    83             if(u==v) continue;
    84             addEdge(u,v);
    85             ++deg[v];
    86         }
    87         if(toposort()) puts("Yes");
    88         else puts("No");
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    chkdsk磁盘修复命令工具怎么用,怎样运行chkdsk工具修复?
    phpMyAdmin 尝试连接到 MySQL 服务器,但服务器拒绝连接。您应该检查配置文件中的主机、用户名和密码
    APiCloud真机调试需要注意的几个问题
    QQ个人文件夹中的文件被占用,解决办法
    PHPExcel读取excel文件
    数据挖掘与机器学习
    什么是数据挖掘?
    数据挖掘相关的10个问题
    PhpStorm 快捷键大全 PhpStorm 常用快捷键和配置
    VirtualBox提示:错误,创建一个新任务失败,被召者解决办法
  • 原文地址:https://www.cnblogs.com/WABoss/p/5155591.html
Copyright © 2011-2022 走看看