POJ 2762 Going from u to v or from v to u?(强连通分量)

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

题意:给定一个有向图。问这个图是否满足下面的性质:对于图中任意两个顶点u和v,存在u到v的路径或者v到u的路径.

思路:步骤如下:

(1)求强连通分量;

(2)缩点:将原图换成新图;

(3)在新图中拓扑排序,若每次只有一个入度为0的点,则满足题意。

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;



struct Node

{

    int v,next;

};



Node edges[6005];

int head[1005],e;

int n,m,C;

int st[1005],top,dfn[1005],low[1005],ID,num,visit[1005];

int p[1005];



void Add(int u,int v)

{

    edges[e].v=v;

    edges[e].next=head[u];

    head[u]=e++;

}



void DFS(int u)

{

    ID++;

    dfn[u]=low[u]=ID;st[top++]=u;visit[u]=1;

    int i,v;

    for(i=head[u];i!=-1;i=edges[i].next)

    {

        v=edges[i].v;

        if(!dfn[v])

        {

            DFS(v);

            low[u]=min(low[u],low[v]);

        }

        else if(visit[v]) low[u]=min(low[u],dfn[v]);

    }

    if(low[u]>=dfn[u])

    {

        num++;

        do

        {

            v=st[top-1];

            visit[v]=0;

            p[v]=num;

            top--;

        }while(v!=u);



    }

}



int g[1005][1005];

int deg[1005];



int OK()

{

    int i,j,u,v,x;

    memset(g,0,sizeof(g));

    memset(deg,0,sizeof(deg));

    for(u=1;u<=n;u++)

    {

        for(i=head[u];i!=-1;i=edges[i].next)

        {

            v=edges[i].v;

            if(p[u]!=p[v]&&!g[p[u]][p[v]])

            {

                g[p[u]][p[v]]=1;

                deg[p[v]]++;

            }

        }

    }

    for(i=1;i<num;i++)

    {

        x=0;

        for(j=1;j<=num;j++) if(deg[j]==0) x++,u=j;

        if(x>1) return 0;

        for(v=1;v<=num;v++) if(g[u][v]) deg[v]--;

        deg[u]=-1;

    }

    return 1;

}



int main()

{

    for(scanf("%d",&C);C--;)

    {

        scanf("%d%d",&n,&m);

        memset(head,-1,sizeof(head));

        e=0;

        int u,v,i;

        for(i=1;i<=m;i++)

        {

            scanf("%d%d",&u,&v);

            Add(u,v);

        }

        top=0;ID=0;num=0;

        memset(dfn,0,sizeof(dfn));

        memset(visit,0,sizeof(visit));

        for(i=1;i<=n;i++) if(!dfn[i]) DFS(i);

        if(OK()) puts("Yes");

        else puts("No");

    }

    return 0;

}

  

你可能感兴趣的:(poj)