POJ 2762 Going from u to v or from v to u?【强连通+toposort】

题意: 给出一个有n 个节点的和m 条单向边,问图中是否任意两点都是连通的,这里连通的定义为:u,v连通,则存在一条从u到v的边或存在一条从v到u的边。

分析:因为在一个强连通分量内部的点是两两可达的,所以可以先对所有的强连通分量缩点,即把强连通分量内部的点看成是一个点。如果两点不可达那么在拓

       扑排序时,该两点谁也不是谁的前驱和后继,所以在拓扑排序时只要同时出现至少两个入度为0的点,那么这些点一定互不可达,所以只要判断拓扑的方式

       是否唯一即可。

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define min(a,b)(a)<(b)?(a):(b)
#define maxn 1005
struct node
{
    int to,next;
}e[100000],edge[1000000];
int tot;
int tt;
int head[maxn];
int toph[maxn];
void add(int s,int t)
{
    e[tot].to=t;
    e[tot].next=head[s];
    head[s]=tot++;
}
void addedge(int s,int t)
{
    edge[tt].to=t;
    edge[tt].next=toph[s];
    toph[s]=tt++;
}
int ti,sn,top,n;
int dfn[maxn];
int low[maxn];
int ins[maxn];
int sta[maxn];
int col[maxn];
int ind[maxn];
void tarjan(int u)
{
    dfn[u]=low[u]=++ti;
    ins[u]=1;
    sta[++top]=u;
    int i,k;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(dfn[k]==0)
        {
            tarjan(k);
            low[u]=min(low[u],low[k]);
        }
        else if(ins[k])
            low[u]=min(low[u],dfn[k]);
    }
    if(dfn[u]==low[u])
    {
        sn++;
        do
        {
            k=sta[top--];
            ins[k]=0;
            col[k]=sn;
        }while(k!=u);
    }
}
int q[maxn];
int toposort()
{
    int front,rear;
    front=rear=0;
    int i,k;
    for(i=1;i<=sn;i++)
        if(ind[i]==0)
            q[rear++]=i;
    if(rear!=1)
        return 0;
    int num=0;
    while(front<rear)
    {
        int x=q[front++];
        int tt=0;
        num++;
        for(i=toph[x];i;i=edge[i].next)
        {
            k=edge[i].to;
            ind[k]--;
            if(ind[k]==0)
            {
                q[rear++]=k;
                tt++;
            }    
        }
        if(tt>1)
            return 0;
    }
    if(num==sn)
        return 1;
    return 0;
}
int main()
{
    int t,m,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        clr(head);
        tot=1;
        int a,b;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
        }
        clr(dfn);
        sn=top=ti=0;
        for(i=1;i<=n;i++)
            if(dfn[i]==0)
                tarjan(i);
        clr(toph);
        tt=1;
        clr(ind);
        for(i=1;i<=n;i++)
            for(j=head[i];j;j=e[j].next)
            {
                k=e[j].to;
                if(col[i]!=col[k])
                {
                    ind[col[k]]++;
                    addedge(col[i],col[k]);
                }
            }
        printf("%s\n",toposort()?"Yes":"No");
    }
    return 0;
}

 

posted @ 2012-10-03 17:39  'wind  阅读(342)  评论(0编辑  收藏  举报