hdu 2767 Proving Equivalences //tarjan+缩点

来源:互联网 发布:windows软件被阻止安装 编辑:程序博客网 时间:2024/06/01 19:56

题目链接

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

先tarjan跑一遍,如果是强连通图就输出0。否则输出max(入度为0的点个数,出度为0的点个数)。

#include <iostream>#include<cstdio>#include<cstring>#include<cmath>#define N 22000#define M 55000using namespace std;struct node{    int to,next;}e[M];int dfn[N],low[N],head[N],in[N],out[N],cnt,scnt,top,q[N],v[N],belong[N],n,m;void init(){    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(in,0,sizeof(in));    memset(out,0,sizeof(out));    memset(belong,0,sizeof(belong));    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 u){    int t;    low[u]=dfn[u]=cnt++;    q[top++]=u;    v[u]=1;    for(int i=head[u];i+1;i=e[i].next)    {        int c=e[i].to;        if(!dfn[c])        {            tarjan(c);            low[u]=min(low[u],low[c]);        }        else if(v[c])            low[u]=min(low[u],dfn[c]);    }    if(low[u]==dfn[u])    {        scnt++;        do        {            t=q[--top];            v[t]=0;            belong[t]=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 t=e[j].to;            if(belong[i]!=belong[t])            {                in[belong[t]]++;                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(){    int T;    cin>>T;    while(T--)    {        cin>>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
原创粉丝点击