• LA 4287 等价性证明


    题目链接:http://vjudge.net/contest/141990#overview

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

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

    把命题看成一个结点,推导看成有向边,就是n个结点,m 条有向边,要求添加尽量少的边,使得新图强连通。

    首先找出强连通分量,把每个强连通分量缩成一个点,得到DAG。设有 a 个结点入度为 0 ,b 个结点出度为 0 ,max(a,b),就是答案。如下图:

    入度为 0 的集合 为 1,出度为 0 的集合 为 2,要加两条红边才能 互相到达(强连通)。

    先标记所有强连通图的入度出度 1 ,要是有点相同,标记为 0 ,统计 入度为 1 ,出度为 1 的个数。

    如果原图只有一个强连通分量 ans = 0 不需要加边。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int Maxn = 20000 + 10;
    vector<int> G[Maxn];
    int pre[Maxn];
    int lowlink[Maxn];
    int sccno[Maxn];
    int dfs_clock;
    int scc_cnt;
    
    stack<int> S;
    
    void dfs(int u)
    {
        pre[u] = lowlink[u] = ++dfs_clock;
        S.push(u);
    
        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)
    {
        dfs_clock = scc_cnt = 0;
        memset(sccno,0,sizeof(sccno));
        memset(pre,0,sizeof(pre));
    
        for(int i=0; i<n; i++)
        {
            if(!pre[i])
                dfs(i);
        }
    
    }
    
    
    int main()
    {
        int n,m;
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(int i=0; i<n; i++)
                G[i].clear();
    
            for(int i=0; i<m; i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                u--;
                v--;
                G[u].push_back(v);
            }
    
            find_scc(n);
    
            int in0[Maxn];
            int out0[Maxn];
            for(int i=1; i<=scc_cnt; i++)
            {
                in0[i] = 1;
                out0[i] = 1;
            }
    
            for(int u=0; u<n; u++)
            {
                for(int i=0; i<G[u].size(); i++)
                {
                    int v = G[u][i];
                    if(sccno[u]!=sccno[v])
                    {
                        in0[sccno[v]] = 0;
                        out0[sccno[u]] = 0;
                    }
                }
            }
    
    
            int maxin = 0,maxout = 0;
    
            for(int i=1; i<=scc_cnt; i++)
            {
                if(in0[i]) maxin ++;
                if(out0[i]) maxout ++;
            }
    
            int ans = max(maxin,maxout);
    
            if(scc_cnt==1)
                puts("0");
            else printf("%d
    ",ans);
    
        }
        return 0;
    }
  • 相关阅读:
    html实现打印预览效果
    layui-table 对表格数据进行处理之后的排序问题
    layui-table与layui-rate评分转换成星级的使用
    使用apache的poi来实现数据导出到excel的功能——方式二
    java获取配置文件中的key=value值
    layDate——设置最大日期不能超过当前日期
    layDate——初步使用
    echarts使用——柱状图
    layui内部定义的function,外部调用时候,提示某函数未定义现象解决方案
    layui table异步调用数据的时候,数据展示不出来现象解决方案
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6075869.html
Copyright © 2020-2023  润新知