hdu 1269

tarjan的裸题  tarjan的主要作用是求有向图中的强联通分量,通过维护两个值,一个是时间戳dfs,一个是low数组,现在理解的还不够深刻,之后理解好了再过来写

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10005;
const int maxm=100005;
struct edge{
    int to,nxt;
}ed[maxm*2+5];
int dfs[maxn],low[maxn],n,m,ecnt,head[maxn],dcnt,s[maxn],scnt,ans;
bool cz[maxn];
void addedge(int f,int t)
{
    ed[++ecnt].to=t;
    ed[ecnt].nxt=head[f];
    head[f]=ecnt;
}
void tarjan(int u)
{
    dfs[u]=low[u]=++dcnt;
    s[++scnt]=u;
    cz[u]=true;//入栈的时候是在 
    for(int i=head[u];i;i=ed[i].nxt)
    {
        int v=ed[i].to;
        if(!dfs[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);//因为有可能有连通块 
        }
        if(cz[v]) low[u]=min(low[u],dfs[v]);
    }
    if(dfs[u]==low[u]) {
    //出栈这里写的不太好 
        ans++;//标识联通分量的个数 
        //cout<<u<<" "<<ans<<endl;
        while(s[scnt]!=u)
        {
            cz[s[scnt]]=false;
            scnt--;
            
        }
        cz[s[scnt]]=false;
        scnt--;    
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        if(n==0&&m==0)  break;
        int a,b;
        memset(head,0,sizeof(head));
        memset(ed,0,sizeof(ed));
        memset(dfs,0,sizeof(dfs));
        memset(low,0,sizeof(low));
        memset(s,0,sizeof(s));
        memset(cz,0,sizeof(cz));
        ecnt=scnt=dcnt=ans=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            addedge(a,b);
        }
        bool t=true;
        for(int i=1;i<=n;i++)
            if(!dfs[i]) tarjan(i);
        if(ans==1) printf("Yes\n");
        else printf("No\n");
    }
    
}
/**
6 8
1 3
1 2
2 4
3 4
3 5
5 6
4 6
4 1
3 3
1 2
2 3
3 1
3 3
1 2
2 3
3 2
0 0
**/

 

posted @ 2017-08-10 22:00  xinyimama  阅读(111)  评论(0)    收藏  举报