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)
  • 相关阅读:
    软件工程(2019)第一次作业
    软件工程-第二次结对编程
    软件工程-第一次结对编程
    java-最大连续子数组和(最大字段和)
    软件工程-第二次作业
    软件工程-第一次作业
    windows下安装oracle11g测试是否成功与监听器问题和网页控制台登录
    java jdk13的安装与环境变量的配置(jre手动生成)
    结对编程第二次作业
    结对作业
  • 原文地址:https://www.cnblogs.com/lochan/p/3852438.html
Copyright © 2011-2022 走看看