zoukankan      html  css  js  c++  java
  • UVAlive4287_Proving Equivalences

    题意是告诉你有n个命题,m条递推关系,表示某个命题可以推出另外一个命题。

    现在问你至少在增加多少个递推关系可以保证所有命题两两互推。

    命题为点,关系为有向边,题目转化成为至少增加多少条有向边使得整个图强连通。

    首先对于有向图,求出所有的联通分量,并且将所有的联通分量缩成一个点,最终得出一个无环图。

    在新图里,设有A个出度为0的点,B个入度为0的点,那么我们只要保证增加max(A,B)条边就可以保证整个图是强连通的。

    这个理解不是很难,只要把所有出度为0的点引出一条边,保证每个入度为0的点引入一条边就可以了。

    召唤代码君:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define maxn 200200
    using namespace std;
    
    int first[maxn],to[maxn],next[maxn],edge;
    int d[maxn],low[maxn],belong[maxn],stack[maxn],top;
    int ind[maxn],outd[maxn],U[maxn],V[maxn];
    int n,m,T,scc,ans1,ans2;
    
    void _init()
    {
        ans1=ans2=scc=top=0,edge=-1;
        for (int i=1; i<=n; i++)
        {
            first[i]=-1;
            d[i]=low[i]=belong[i]=0;
        }
    }
    
    void addedge(int uu,int vv)
    {
        edge++;
        to[edge]=vv,next[edge]=first[uu],first[uu]=edge;
    }
    
    void dfs(int cur,int fa)
    {
        d[cur]=low[cur]=d[fa]+1;
        stack[++top]=cur;
        for (int i=first[cur]; i!=-1; i=next[i])
        {
            if (belong[to[i]]) continue;
            if (!d[to[i]]) dfs(to[i],cur);
            low[cur]=min(low[cur],low[to[i]]);
        }
        if (low[cur]>=d[cur])
            for (scc++,ind[scc]=outd[scc]=0;stack[top+1]!=cur;) belong[stack[top--]]=scc;
    }
    
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d%d",&n,&m);
            _init();
            for (int i=1; i<=m; i++)
            {
                scanf("%d%d",&U[i],&V[i]);
                addedge(U[i],V[i]);
            }
            for (int i=1; i<=n; i++)
                if (!d[i]) dfs(i,0);
            for (int i=1; i<=m; i++)
            {
                if (belong[U[i]]==belong[V[i]]) continue;
                outd[belong[U[i]]]++;
                ind[belong[V[i]]]++;
            }
            for (int i=1; i<=scc; i++)
            {
                if (ind[i]==0) ans1++;
                if (outd[i]==0) ans2++;
            }
            if (scc==1) ans1=ans2=0;
            printf("%d
    ",max(ans1,ans2));
        }
        return 0;
    }
    如有转载,请注明出处(http://www.cnblogs.com/lochan)
  • 相关阅读:
    你还在钟情于windows XP吗?
    我常用的vim快捷键
    2013年读的书(很多还没看完)
    期末考试了
    顺着自己的心,去做自己喜欢的事
    关于最近新闻泛滥的几点看法以及学习的个人观点
    华为OJ_1
    【Android】弹出软键盘时候让上面布局跟着上移的方法
    【Android】策略模式封装百度地图路线规划模块
    google觉得好用的插件(不断更新)
  • 原文地址:https://www.cnblogs.com/lochan/p/3852438.html
Copyright © 2011-2022 走看看