• UVALive


    给定n个命题之间的已经证明的关系如 a b表示已经证明蕴含式a→b,要求还需要再作多少次证明使得所有的命题都是等价的.将每个命题看成一个点,已经证明的命题之间连一条边,问题转化为添加多少条单向边使得图成为一个强连通分量.

    先求出所有的强连通分量,然后缩点构成一个SCC图,统计其中入度为0的点个数a,以及出度为0的点的个数b,max(a,b)就是需要再作的证明.注意当图一开始就是强连通时,不需要作出证明了.

    来自刘汝佳算法训练指南代码:

    #include <iostream>
    #include <sstream>
    #include <cstdio>
    #include <climits>
    #include <cstring>
    #include <cstdlib>
    #include <string>
    #include <stack>
    #include <map>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <algorithm>
    #define esp 1e-6
    #define pi acos(-1.0)
    #define pb push_back
    #define mp(a, b) make_pair((a), (b))
    #define in  freopen("in.txt", "r", stdin);
    #define out freopen("out.txt", "w", stdout);
    #define print(a) printf("%d
    ",(a));
    #define bug puts("********))))))");
    #define stop  system("pause");
    #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
    #define pragma comment(linker, "/STACK:102400000, 102400000")
    #define inf 0x0f0f0f0f
    
    using namespace std;
    typedef long long  LL;
    typedef vector<int> VI;
    typedef pair<int, int> pii;
    typedef vector<pii,int> VII;
    typedef vector<int>:: iterator IT;
    const int maxn = 22222;
    int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
    int in0[maxn], out0[maxn];
    VI g[maxn];
    stack<int> S;
    void dfs(int u)
    {
        S.push(u);
        lowlink[u] = pre[u] = ++dfs_clock;
        for(int i = 0; i < g[u].size(); i++)
        {
            int v = g[u][i];
            if(!pre[v])
            {
                dfs(v);
                lowlink[u] = min(lowlink[u], lowlink[v]);
            }
            else if(!sccno[v])
            {
                lowlink[u] = min(lowlink[u], pre[v]);
            }
        }
        if(lowlink[u] == pre[u])
        {
            scc_cnt++;
            for(;;)
            {
                int x = S.top();
                S.pop();
                sccno[x] = scc_cnt;
                if(x == u) break;
            }
        }
    }
    void find_scc(int n)
    {
        memset(pre, 0, sizeof(pre));
        memset(sccno, 0, sizeof(sccno));
        dfs_clock = scc_cnt = 0;
        for(int i = 0; i < n; i++)
            if(!pre[i]) dfs(i);
    }
    int main(void)
    {in
        int n, m;
        int T;
        for(int t = scanf("%d", &T); t <= T; t++)
        {
            for(int i = 0; i < maxn; i++)
                g[i].clear();
            memset(in0, 1, sizeof(in0));
            memset(out0, 1, sizeof(out0));
            scanf("%d%d", &n, &m);
            while(m--)
            {
                int u, v;
                scanf("%d%d", &u, &v);
                u--, v--;
                g[u].pb(v);
            }
            find_scc(n);
            for(int u = 0; u < n; u++)
                for(int i = 0; i < g[u].size(); i++)
                {
                    int v = g[u][i];
                    if(sccno[v] != sccno[u])
                        in0[sccno[v]] = out0[sccno[u]] = 0;
                }
            int a = 0, b= 0;
            for(int i = 1; i <= scc_cnt; i++)
            {
                if(in0[i]) a++;
                if(out0[i]) b++;
            }
            int ans = 0;
            if(scc_cnt != 1) ans = max(a, b);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    WDF CSS 书写规范
    瞬间之美web界面设计如何让用户心动 读后感(一)
    ubuntu install node0.8.9 to the current user
    js单元测试_jsTestDriver
    window.print
    Java内省
    jQuery源代码学习jQuery对象扩展
    jdk集合结构
    【转载】程序员(1)
    【装载】JAVA虚拟机的内存模型
  • 原文地址:https://www.cnblogs.com/rootial/p/3336494.html
Copyright © 2020-2023  润新知