zoukankan      html  css  js  c++  java
  • UVALive 4287 SCC-Tarjan 加边变成强连通分量

    还是强连通分量的题目,但是这个题目不同的在于,问你最少要添加多少条有向边,使得整个图变成一个强连通分量

    然后结论是,找到那些入度为0的点的数目 和 出度为0的点的数目,取其最大值即可,怎么证明嘛。。。我也不好怎么证,不过细细一琢磨发现就是这样,改天找聪哥一起探讨下怎么证明

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <stack>
    using namespace std;
    const int N=20010;
    int pre[N],lowlink[N],sccno[N];
    vector<int>G[N],G2[N];
    stack<int> sta;
    int n,m,vis[N],scc_cnt,dfs_clk;
    int ind[N],outd[N];
    void init()
    {
        for (int i=0;i<=n;i++){
            pre[i]=0;
            lowlink[i]=0;
            sccno[i]=0;
            G[i].clear();
            G2[i].clear();
            vis[i]=0;
            scc_cnt=dfs_clk=0;
            ind[i]=outd[i]=0;
        }
    }
    void dfs(int u)
    {
        pre[u]=lowlink[u]=++dfs_clk;
        sta.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=sta.top();sta.pop();
                sccno[x]=scc_cnt;
                if (x==u) break;
            }
        }
    }
    void tarjan()
    {
        for (int i=1;i<=n;i++){
            if (!pre[i]) dfs(i);
        }
        for (int i=1;i<=n;i++){
            int u=sccno[i];
            for (int j=0;j<G[i].size();j++){
                int v=G[i][j];
                v=sccno[v];
                if (u!=v){
                    G2[u].push_back(v);
                    ind[v]++;
                    outd[u]++;
                }
            }
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while (t--)
        {
            scanf("%d%d",&n,&m);
            init();
            int a,b;
            while (m--){
                scanf("%d%d",&a,&b);
                G[a].push_back(b);
            }
            tarjan();
            if (scc_cnt==1){
                puts("0");
                continue;
            }
            int ans1=0,ans2=0;
            for (int i=1;i<=scc_cnt;i++){
                if (ind[i]==0) ans1++;
                if (outd[i]==0) ans2++;
            }
            printf("%d
    ",max(ans1,ans2));
        }
        return 0;
    }
    

      

  • 相关阅读:
    国内外常用学术论文搜索网站
    2019年全国高校sql数据库
    Flask无法访问(127.0.0.1:5000)的问题解决方法
    Windows终端命令行工具Cmder
    JQuery实现密码可见不可见
    区块链最大的难题及其解决方案
    python 下载 进度条
    centos 用docker 运行 cypress
    通过 centos Nginx 查看html (为后续 服务器生成html 方便访问)
    odoo 分享 PostgreSQL 语句2
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3902995.html
Copyright © 2011-2022 走看看