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

题意:数学的稳定证明,也就是一个定义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;
}





你可能感兴趣的:(HDU 2767 Proving Equivalences 增加最小边使图为强连通)