hdu 1269

题意:判断是否为强连通图

解题思路:判断强连通分量是否为1 K算法

zsd:

1 对原图进行深度优先搜索 记录每个顶点的dfn值

2 将图反向 得到逆图

3 选择从当前dfn值最大的定点出发,对逆图进行dfs搜索,删除能遍历到得顶点 这些顶点构成一个强连通分量

4如果还有顶点没有删除继续执行3步

第一种解法;
#include<iostream> using namespace std; struct G { int dest; G *next; }; int n,m; G *ga[10001]; G *gt[10001]; int path[10001]; int vis[10001]; void addedge(G *g[],int i,int j) { G *l=new G; l->dest=j; l->next=g[i]; g[i]=l; } void dfsa(int u) { G *l=ga[u]; if(!vis[u]) { vis[u]=1; for(l;l!=NULL;l=l->next) dfsa(l->dest); path[0]++; path[path[0]]=u; } } void dfst(int u) { G *l=gt[u]; if(!vis[u]) { vis[u]=1; for(l;l!=NULL;l=l->next) dfst(l->dest); } } void k() { int i; path[0]=0; memset(vis,0,sizeof(vis)); //搜索原图 for(i=1;i<=n;i++) { if(!vis[i]) dfsa(i); } memset(vis,0,sizeof(vis)); int sum=0; for(i=n;i>=1;i--) { if(!vis[path[i]]) { sum++; dfst(path[i]); } } if(sum>1) printf("No\n"); else printf("Yes\n"); } int main() { int a,b; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; for(int i=1;i<=n;i++) ga[i]=gt[i]=NULL; while(m--) { scanf("%d%d",&a,&b); addedge(ga,a,b); addedge(gt,b,a); } k(); } return 0; }
第二种解法:
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
const int Max=11000;
#define min(a,b) a>b?b:a
int n,m,top,index;
int instack[Max],stack[Max],loop[Max];
int DFN[Max],LOW[Max],ans;
vector<int> V[Max];
void init()
{
    top=ans=0;
    index=1;
    int i;
    for(i=0;i<Max;i++)
    {
        V[i].clear();
        loop[i]=0;
        instack[i]=0;
    }
}
void tarjan(int u)
{
    int i,j,v;
    LOW[u]=DFN[u]=index++;
    stack[top++]=u;
    loop[u]=1;
    instack[u]=1;
    for(i=0;i<V[u].size();i++)//考虑所有与u相连的边
    {
        v=V[u][i];
        if(loop[v]==0)//如果v还没有访问过
        {
            tarjan(v);//dfs(v)
            LOW[u]= min(LOW[u],LOW[v]);
        }
       else if(instack[v])//否则是反向边
            LOW[u]= min(LOW[u],DFN[v]);//low[u]为u节点能追溯到得最早的节点编号
        
    }
    if(DFN[u]==LOW[u])//如果此节点的dfn[u]与low[u]相等 则说明以u为节点的搜索树上的所有节点是一个强连通分量
    {
        do{ //把所有的强连通节点出栈
            j=stack[top-1];
            instack[j]=0;
            top--;
        }while(j!=u);
        ans++;//强连通分量的个数
    }
}
int main()
{
    int i,j,x,y;
    while(~scanf("%d%d",&n,&m)&&n+m)
    {
        init();
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            V[x].push_back(y);
        }
        for(i=1;i<=n;i++)
            if(loop[i]==0)
                   tarjan(i);
        if(ans==1||n==1)
            printf("Yes\n");
        else
            printf("No\n");
    }
}

 

posted @ 2014-05-06 16:23  _一千零一夜  阅读(240)  评论(0编辑  收藏  举报