2767 Proving Equivalences 至少加几条边让全部图变成强连通模板题

#include<stdio.h>
#include<string.h>
#define N 21000
struct node {
int u,v,next;
}bian[N*3];
int head[N],dfn[N],low[N],index,vis[N],stac[N],top,yong,cnt,suo[N],indegree[N],outdegree[N];
void init() {
yong=0;index=0;top=0;cnt=0;
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(indegree,0,sizeof(indegree));
memset(outdegree,0,sizeof(outdegree));
}
void addedge(int u,int v) {
bian[yong].u=u;
bian[yong].v=v;
bian[yong].next=head[u];
head[u]=yong++;
}
int Min(int a,int b) {
return a>b?b:a;
}
void tarjan(int u){
 dfn[u]=low[u]=++index;
 vis[u]=1;
 stac[++top]=u;
 int i;
 for(i=head[u];i!=-1;i=bian[i].next) {
    int v=bian[i].v;
    if(!dfn[v]) {
        tarjan(v);
        low[u]=Min(low[u],low[v]);
    }
    else
    if(vis[v])
    low[u]=Min(low[u],dfn[v]);
 }
 if(low[u]==dfn[u]) {
    ++cnt;
    int t;
    do{
        t=stac[top--];
        suo[t]=cnt;
        vis[t]=0;
    }while(t!=u);
 }
}
int main() {
  int n,m,i,in,ou,a,b,t;
  scanf("%d",&t);
  while(t--) {
    scanf("%d%d",&n,&m);
    if(m==0) {
        printf("%d
",n);
        continue;
    }
    init();
    while(m--) {
        scanf("%d%d",&a,&b);
        addedge(a,b);
    }
    for(i=1;i<=n;i++)
    if(!dfn[i])
        tarjan(i);
        if(cnt==1) {//剁手
            printf("0
");
            continue;
        }
    for(i=0;i<yong;i++)
    if(suo[bian[i].u]!=suo[bian[i].v]) {
        indegree[suo[bian[i].v]]++;
        outdegree[suo[bian[i].u]]++;
    }
    in=0;ou=0;
    for(i=1;i<=cnt;i++) {
        if(indegree[i]==0)
            in++;
            if(outdegree[i]==0)
                ou++;
            }
            printf("%d
",in>ou?in:ou);
  }
return 0;
}

原文地址:https://www.cnblogs.com/thefirstfeeling/p/4410695.html