UVALive-4287 Proving Equivalences (有向图的强连通分量)

题目大意:有n个命题,已知其中的m个推导,要证明n个命题全部等价(等价具有传递性),最少还需要做出几次推导。

题目分析:由已知的推导可以建一张无向图,则问题变成了最少需要增加几条边能使图变成强连通图。找出所有的强连通分量,将每一个连通分量视作一个大节点,则整张图变成了一张DAG。设出度为0的大节点个数为a,入度为0的大节点个数为b,则答案就是max(a,b)。为什么是这样呢?因为要使等价证明前进下去,每个大节点的出度和入度都必须不能是0。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<stack>
# include<cstring>
# include<algorithm>
using namespace std;

const int maxn=20005;
int n,m,low[maxn],pre[maxn],sccno[maxn],in[maxn],out[maxn],dfs_cnt,scc_cnt;
stack<int>S;
vector<int>G[maxn];

void dfs(int u)
{
    low[u]=pre[u]=++dfs_cnt;
    S.push(u);
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(!pre[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);
        }else if(!sccno[v])
            low[u]=min(pre[v],low[u]);
    }
    if(low[u]==pre[u]){
        ++scc_cnt;
        while(1){
            int x=S.top();
            S.pop();
            sccno[x]=scc_cnt;
            if(x==u)
                break;
        }
    }
}

void findScc()
{
    memset(low,0,sizeof(low));
    memset(pre,0,sizeof(pre));
    memset(sccno,0,sizeof(sccno));
    dfs_cnt=scc_cnt=0;
    for(int i=0;i<n;++i)   if(!pre[i])
        dfs(i);
}

void read()
{
    int a,b;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)  G[i].clear();
    while(m--)
    {
        scanf("%d%d",&a,&b);
        --a,--b;
        G[a].push_back(b);
    }
}

void solve()
{
    for(int i=1;i<=scc_cnt;++i)
        in[i]=out[i]=1;///先假设所有分量的出度和入度都是0;
    for(int i=0;i<n;++i)
        for(int j=0;j<G[i].size();++j)
            if(sccno[i]!=sccno[G[i][j]])
                out[sccno[i]]=in[sccno[G[i][j]]]=0;///如果i和G[i][j]不在一个分量内,则其对应的出度和入度不是0;
    int a=0,b=0;
    for(int i=1;i<=scc_cnt;++i){
        if(in[i])   ++a;
        if(out[i])  ++b;
    }
    int ans=max(a,b);
    if(scc_cnt==1)
        ans=0;
    printf("%d\n",ans);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        read();
        findScc();
        solve();
    }
    return 0;
}

  

posted @ 2015-10-21 19:15  20143605  阅读(271)  评论(0编辑  收藏  举报