• poj 2762(强连通分量+拓扑排序)


    题目链接:http://poj.org/problem?id=2762

    题意:给出一个有向图,判断任意的两个顶点(u,v)能否从u到达v,或v到达u,即单连通,输出Yes或No.

    分析:对于同一个强连通分量而言,所有的点都是互达的,如果该有向图只有一个强连通分量,则肯定是Yes了;

    若有多个强连通分量呢?判断两个不同的强连通分量的点u和v是否单连通,缩点后,建新图,用拓扑排序判断,删除点的时候若发现有大于2个点的入度为0,则u和v必定不能连通。

    AC代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 const int N=1000+5;
      4 const int M=6000+5;
      5 struct EDGE{
      6     int v,next;
      7 }edge[M],edge2[M];
      8 int first[N],low[N],dfn[N],sta[M],belong[N],que[M],in[N],first2[N];
      9 bool instack[N],map[N][N];
     10 int cnt,g,scc,top,k;
     11 void AddEdge(int u,int v)
     12 {
     13     edge[g].v=v;
     14     edge[g].next=first[u];
     15     first[u]=g++;
     16 }
     17 void AddEdge2(int u,int v)
     18 {
     19     edge2[k].v=v;
     20     edge2[k].next=first2[u];
     21     first2[u]=k++;
     22 }
     23 int min(int a,int b)
     24 {
     25     return a<b?a:b;
     26 }
     27 void Tarjan(int u)    //求强连通分量
     28 {
     29     int i,v;
     30     low[u]=dfn[u]=++cnt;
     31     sta[++top]=u;
     32     instack[u]=true;
     33     for(i=first[u];i!=-1;i=edge[i].next)
     34     {
     35         v=edge[i].v;
     36         if(!dfn[v])
     37         {
     38             Tarjan(v);
     39             low[u]=min(low[u],low[v]);
     40         }
     41         else if(instack[v])
     42             low[u]=min(low[u],dfn[v]);
     43     }
     44     if(low[u]==dfn[u])
     45     {
     46         scc++;
     47         while(1)
     48         {
     49             v=sta[top--];
     50             instack[v]=false;
     51             belong[v]=scc;    //缩点
     52             if(v==u)
     53                 break;
     54         }
     55     }
     56 }
     57 void build(int n)    //建缩点后的新图
     58 {
     59     int u,i,v,a,b;
     60     memset(map,false,sizeof(map));
     61     memset(first2,-1,sizeof(first2));
     62     memset(in,0,sizeof(in));
     63     k=0;
     64     for(u=1;u<=n;u++)      //遍历每个顶点的出边
     65     {
     66         for(i=first[u];i!=-1;i=edge[i].next)
     67         {
     68             v=edge[i].v;
     69             a=belong[u];
     70             b=belong[v];
     71             if(a==b)     //若属于同一个强连通分量
     72                 continue;
     73             if(!map[a][b])
     74             {
     75                 AddEdge2(a,b);   //建新边
     76                 map[a][b]=true;
     77                 in[b]++;
     78             }
     79         }
     80     }
     81 }
     82 int topo()   //拓扑排序
     83 {
     84     int i,front,rear,top,v;
     85     front=rear=0;
     86     for(i=1;i<=scc;i++)
     87         if(in[i]==0)
     88         {
     89             que[rear++]=i;
     90         }
     91     if(rear-front>1)    //入度为0的顶点个数大于1,则无解
     92         return 0;
     93     while(front<rear)
     94     {
     95         top=que[front++];
     96         for(i=first2[top];i!=-1;i=edge2[i].next)
     97         {
     98             v=edge2[i].v;
     99             in[v]--;
    100             if(in[v]==0)
    101             {
    102                 que[rear++]=v;
    103             }
    104             if(rear-front>1)
    105                 return 0;
    106         }
    107     }
    108     return 1;      //有解
    109 }
    110 int main()
    111 {
    112     int t,n,m,i,u,v;
    113     scanf("%d",&t);
    114     while(t--)
    115     {
    116         scanf("%d%d",&n,&m);
    117         g=cnt=top=scc=0;
    118         memset(first,-1,sizeof(first));
    119         memset(dfn,0,sizeof(dfn));
    120         memset(instack,false,sizeof(instack));
    121         while(m--)
    122         {
    123             scanf("%d%d",&u,&v);
    124             AddEdge(u,v);
    125         }
    126         for(i=1;i<=n;i++)    //求强连通分量
    127             if(!dfn[i])
    128                 Tarjan(i);
    129         build(n);     //建缩点后的新图
    130         if(topo())    //拓扑排序
    131             printf("Yes
    ");
    132         else
    133             printf("No
    ");
    134     }
    135     return 0;
    136 }
    View Code
  • 相关阅读:
    Python logging根据时间创建日志文件
    ORACLE Merge into 使用
    go安装goctl
    Oracle 行转列
    ORACLE with as查询优化
    Linux环境使用Docker安装MongoDb
    Linux环境使用Docker安装MySql
    Docker基础操作
    Linux基础命令
    Ansible自动化运维介绍
  • 原文地址:https://www.cnblogs.com/frog112111/p/3383009.html
Copyright © 2020-2023  润新知