HDU 2767 Proving Equivalences 增加最小边使图为强连通

来源:互联网 发布:it女神 编辑:程序博客网 时间:2024/05/02 01:05

题意:数学的稳定证明,也就是一个定义x可以通过若干次的等价变换再次转换到x则表示定义x与在变换过程中用到的定义为稳定的,问至少还要添加多少条等价变换可以使给出的所有定义稳定?


想法:tarjan缩点,Max(入度=0点的个数,出度=0点的个数)


#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<stack>#define mm(x) memset(x,0,sizeof(x))using namespace std;const int N=20000+5;vector<int>G[N];stack<int>s;int dfn[N],low[N];int indegree[N],outdegree[N];int instack[N];int paint[N];int index,col;int MIN(int a,int b){    if(a<b) return a;    return b;}int MAX(int a,int b){    if(a>b) return a;    return b;}void Init(int n){    index=col=1;    for(int i=0;i<=n;i++)    G[i].clear();    while(!s.empty()) s.pop();    mm(dfn);    mm(low);    mm(indegree);    mm(outdegree);    mm(instack);    mm(paint);}void Tarjan(int u){    dfn[u]=low[u]=index++;    instack[u]=1;    s.push(u);    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(!dfn[v])        {            Tarjan(v);            low[u]=MIN(low[u],low[v]);        }        else if(instack[v])        {            low[u]=MIN(low[u],dfn[v]);        }    }    if(low[u]==dfn[u])    {        int k=s.top();        while(k!=u)        {            s.pop();            instack[k]=0;            paint[k]=col;            k=s.top();        }        s.pop();        instack[u]=0;        paint[u]=col;        col++;    }}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        if(m==0)        {            printf("%d\n",n);            continue;        }        Init(n);        for(int i=0;i<m;i++)        {            int a,b;            scanf("%d%d",&a,&b);            G[a].push_back(b);        }         for(int i=1;i<=n;i++)        {            if(!dfn[i])            {                Tarjan(i);            }        }        col--;        if(col==1)        {            printf("0\n");            continue;        }        for(int i=1;i<=n;i++)        {            for(int j=0;j<G[i].size();j++)            {                int a=i,b=G[i][j];                if(paint[a]!=paint[b])                {                    outdegree[paint[a]]++;                    indegree[paint[b]]++;                }            }        }        int in=0,out=0;        for(int i=1;i<=col;i++)        {            if(!indegree[i]) in++;            if(!outdegree[i]) out++;        }        printf("%d\n",MAX(in,out));    }    return 0;}





0 0