hdu 3836 Equivalent Sets //tarjan+缩点

来源:互联网 发布:淘宝网韩都衣舍男装 编辑:程序博客网 时间:2024/04/29 17:13

题目链接

题意:给n个点和m条有向边,问最少再加几条边使其变成强连通图。和hdu2767同样的解法。

#include <iostream>#include<cstdio>#include<cmath>#include<cstring>#define N 22000#define M 55000using namespace std;struct node{    int next,to;}e[M];int head[N],cnt,scnt,top,n,m,dfn[N],low[N],v[N],belong[N],in[N],out[N],q[N];void init(){    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(v,0,sizeof(v));    memset(belong,0,sizeof(belong));    memset(in,0,sizeof(in));    memset(out,0,sizeof(out));    cnt=scnt=top=0;}void add_edge(int u,int v){    e[cnt].to=v;    e[cnt].next=head[u];    head[u]=cnt++;}void tarjan(int t){    low[t]=dfn[t]=cnt++;    q[top++]=t;    v[t]=1;    for(int i=head[t];i+1;i=e[i].next)    {        int u=e[i].to;        if(!dfn[u])        {            tarjan(u);            low[t]=min(low[t],low[u]);        }        else if(v[u])            low[t]=min(low[t],dfn[u]);    }    int u;    if(low[t]==dfn[t])    {        scnt++;        do        {            u=q[--top];            v[u]=0;            belong[u]=scnt;        }while(t!=u);    }}void solve(){    for(int i=1;i<=n;i++)        if(!dfn[i]) tarjan(i);    if(scnt==1)    {        cout<<0<<endl;        return;    }    for(int i=1;i<=n;i++)        for(int j=head[i];j+1;j=e[j].next)        {            int u=e[j].to;            if(belong[u]!=belong[i])            {                in[belong[u]]++;                out[belong[i]]++;            }        }    int a=0,b=0;    for(int i=1;i<=scnt;i++)    {        if(in[i]==0)    a++;        if(out[i]==0)   b++;    }    cout<<max(a,b)<<endl;}int main(){    while(~scanf("%d%d",&n,&m))    {        init();        for(int i=0;i<m;i++)        {            int u,v;            scanf("%d%d",&u,&v);            add_edge(u,v);        }        solve();    }}

0 0