hdu 3594 强连通好题仙人掌图,对自己的tarjan模板改下用这个

#include<stdio.h>
#include<string.h>
#define N 21000
struct node {
int v,next;
}bian[51000];
int yong,dfn[N],low[N],stac[N],top,index,visit[N],ans,flag,mark[N],head[N],pre[N];
void init() {//初始化
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(mark,0,sizeof(mark));
memset(visit,0,sizeof(visit));
memset(head,-1,sizeof(head));
memset(pre,0,sizeof(pre));
flag=0;yong=0;
index=0;top=0;ans=0;
memset(stac,0,sizeof(stac));
}
void addedge(int u,int v) {
bian[yong].v=v;
bian[yong].next=head[u];
head[u]=yong++;
}
int MIN(int a,int b) {
return a>b?b:a;
}
void judge(int v,int u) {//对于每一个强连通分量对边的两边的点增一
while(pre[u]!=v) {
    mark[u]++;
    if(mark[u]>1) {
        flag=1;return ;
    }
    u=pre[u];
}
return ;
}
void tarjan(int u) {
 dfn[u]=low[u]=++index;
 stac[++top]=u;
 visit[u]=1;
 int i;
 for(i=head[u];i!=-1;i=bian[i].next) {
    int v=bian[i].v;
    if(dfn[v]==0) {
        pre[v]=u;
        tarjan(v);
        if(flag)
            return ;
      low[u]=MIN(low[u],low[v]);
    }
    else if(visit[v]) {
        judge(v,u);
        if(flag)return ;
        low[u]=MIN(low[u],dfn[v]);
    }
 }
 if(dfn[u]==low[u]) {
    ans++;
    if(ans>1){//判断是否是一个强联通图
        flag=1;return ;
    }
    int t;
    do{
        t=stac[top--];
        visit[t]=0;
    }while(t!=u);
 }
 return ;
}
int main() {
      int t,n,a,b,i;
      scanf("%d",&t);
      while(t--) {
            init();
        scanf("%d",&n);
        while(scanf("%d%d",&a,&b),a||b) {
            addedge(a,b);
        }
        for(i=0;i<n;i++) {
                if(!dfn[i])
            tarjan(i);
        if(flag)break;
        }
        if(flag==0)
            printf("YES\n");
        else
            printf("NO\n");
      }
return 0;
}

转载于:https://www.cnblogs.com/thefirstfeeling/p/4410708.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值