hdu 2767 Proving Equivalences (tarjan + 缩点)

来源:互联网 发布:java搭建项目的流程 编辑:程序博客网 时间:2024/05/19 01:32

/*题目大意:给定一张有向图,问最少添加几条边使得有向图成为一个强连通图。解题思路:缩点后找入度为0的点和出度为0的点,统计个数,选择大的那个数就是答案。         如果出度为0的个数n比入度为0的个数m多,那添加n条边,从当前出度为0的点到         其他入度为0的点,肯定能成为强连通图,同理可得m大也可以。(各连通分支间         可能需要1条或2条,才能使两个连通分支相互连通。)*/#include<iostream>#include<string.h>#define size 20010using namespace std;int dfn[size],low[size];int head[size] , stack[size] , in[size];int lian[size] ,rd[size] ,cd[size];struct E {   int v , next;}e[50050];int n,m,sum , top ,step , s;void init(){     for(int i=0;i<size;i++)     {         dfn[i]=low[i]=stack[i]=in[i]=lian[i]=0; head[i]=-1;     }     top=0;  sum=step=0; s=-1;}void insert(int u , int v){    e[top].v=v;   e[top].next=head[u]; head[u]=top++;}void tarjan(int u){    int v;    dfn[u]=low[u]=++step;    in[u]=1;      stack[++s]=u;    for(int i=head[u];i!=-1;i=e[i].next)    {        v=e[i].v;        if(!dfn[v])        {            tarjan(v);            if(low[v]<low[u]) low[u]=low[v];        }        else if(in[v] && dfn[v]<low[u])  low[u]=dfn[v];    }    if(dfn[u]==low[u])    {        sum++;           do        {            v=stack[s--];               in[v]=0;            lian[v]=sum;        }while(u!=v);    }}int main(){    int t;    int a, b;    scanf("%d",&t);    int rds,cds;    while(t--)    {         init();         rds=cds=0;         scanf("%d%d",&n,&m);         for(int i=0;i<m;i++)           {              scanf("%d%d",&a,&b);              insert(a, b);          }         for(int i=1;i<=n;i++)         if(!dfn[i]) tarjan(i);            if(sum==1)   printf("0\n");         else         {             for(int i=0;i<=sum;i++) rd[i]=cd[i]=0;             for(int i=1;i<=n;i++)             {                for(int j=head[i];j!=-1; j=e[j].next)                {                    int v=e[j].v;                    if(lian[i]!=lian[v])                    {                        cd[lian[i]]++;                        rd[lian[v]]++;                    }                }             }             for(int i=1;i<=sum;i++)             {                  if(cd[i]==0) cds++;                  if(rd[i]==0) rds++;             }             if(cds>rds) printf("%d\n",cds);             else printf("%d\n",rds);         }    }    return 0;}


原创粉丝点击