pku 2762Going from u to v or from v to u (求强连通分量+缩点+拓扑排序)

题目大意:给定有向图,任意给出两个点u、v,如果u到v有路或者v到u有路则输出Yes,否则输出No。

思路:求出强连通分量,然后缩点(建立新图),然后在这张新图中,拓扑排序一下,看拓扑排序是否唯一,如果唯一,则说明这个新图能构成一条最长的链,那么不是u到v有路,就是v到u有路了,输出Yes.

参考代码如下:

#include <stdio.h>
#include <string.h>

 

#define VN 1005
#define EN 6005

 

typedef struct ENode
{
    int adv;
    ENode *next;
} ENode;
ENode newnode[EN],newnode2[EN];
int newn,newn2;

typedef struct VNode
{
    ENode *first;
} VNode;
VNode adjlist[VN],adjlist2[VN];

 

void insert(int i,int j)
{
    ENode *p=newnode+newn++;
    p->adv=j;
    p->next=adjlist[i].first;
    adjlist[i].first=p;
}
void insert2(int i,int j)
{
    ENode *p=newnode2+newn2++;
    p->adv=j;
    p->next=adjlist2[i].first;
    adjlist2[i].first=p;
}

int DFN[VN],LOW[VN],vcnt,belong[VN],bcnt,stack[VN],top;
bool instack[VN],indegree[VN];

void init(int n)
{
    newn=0;
    newn2=0;
    memset(adjlist,0,n*sizeof(*adjlist));
    memset(adjlist2,NULL,n*sizeof(*adjlist));
    memset(DFN,0,4*n);
    vcnt=0;
    memset(belong,0,4*n);
    bcnt=0;
    top=-1;
    memset(instack,false,n);
    memset(indegree,false,n);
}

void tarjan(int u)
{
    DFN[u]=LOW[u]=++vcnt;
    stack[++top]=u;
    instack[u]=true;
    int v;
    ENode *p=NULL;
    for(p=adjlist[u].first; p ; p=p->next)
    {
        v=p->adv;
        if(DFN[v]==0)
        {
            tarjan(v);
            if(LOW[u]>LOW[v])
                LOW[u]=LOW[v];
        }
        else if(instack[v] && LOW[u]>DFN[v])
            LOW[u]=DFN[v];
    }
    if(LOW[u]==DFN[u])
    {
        bcnt++;
        do
        {
            v=stack[top--];
            instack[v]=false;
            belong[v]=bcnt;
        }
        while(v!=u);
    }
}

void display(int n)
{
    ENode *p;
    int i;
    for(i=1; i<=n; i++)
    {
        printf("%d: ",i);
        for(p=adjlist[i].first; p; p=p->next)
        {
            printf("%d ",p->adv);
        }
        printf("\n");
    }
}

bool TopologicalSort()
{
    ENode *p=NULL;
    int i,index,num,end=1;
    for(end=1; end<=bcnt; end++)
    {
        num=0;
        for(i=1; i<=bcnt; i++)
        {
            if(indegree[i]==false)//缩点 入度为0
            {
                index=i;
                num++;
            }
        }
        if(num==0 || num>1) return false;
        indegree[index]=true;
        for(p=adjlist2[index].first; p; p=p->next)
            indegree[p->adv]=false;
    }
    return true;
}

int main()
{
    int test;
    scanf("%d",&test);
    while(test--)
    {
        int N,M,i,j;
        scanf("%d %d",&N,&M);
        init(N+1);
        while(M--)
        {
            scanf("%d %d",&i,&j);
            insert(i,j);
        }
        for(i=1; i<=N; i++)
            if(DFN[i]==0)
                tarjan(i);
        ENode *p=NULL;
        for(i=1; i<=N; i++)
        {
            for(p=adjlist[i].first; p; p=p->next)
            {
                j=p->adv;
                if(belong[i]!=belong[j])
                {
                    indegree[belong[j]]=true;
                    insert2(belong[i],belong[j]);
                }
            }
        }
        if(TopologicalSort())
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

 

posted @ 2010-08-18 17:22  菜到不得鸟  阅读(362)  评论(0)    收藏  举报