zoukankan      html  css  js  c++  java
  • Network of Schools POJ

    题目大意

        有N个学校,这些学校之间用一些单向边连接,若学校A连接到学校B(B不一定连接到A),那么给学校A发一套软件,则学校B也可以获得。现给出学校之间的连接关系,求出至少给几个学校分发软件,才能使得所有的学校均可以获得软件;以及,至少需要添加几条单向边连接学校,才能使得给这些学校中任何一所发软件,其余的学校均可以收到。

    题目分析

        在一个图中,强连通分支内的任何一个点被“发软件”,则分支内的所有点均可以获得,因此首先求出强连通分支,将强连通分支合并为一点来看。 
        重构之后的图若只有一个点,则只需要向任何一所学校发送即可。即结果为1(至少向1所学校发布软件) 0(不需要添加新边来使得整个图连通). 
        重构之后的图若有多个点,则考虑这些点中入度为0的点:入度为0的点不能被其他点到达,而一个入度不为0的点可以从某个入度为0的点到达,那么只需要向这些入度为0的点分发软件,就可以使得所有的点均能获得软件。 
        重构之后的图中有出度为0的点,在图中,入度为0的点(设为m个)无法从其他点到达,那么为了使得所有的点连通,需要m条路径连接到这m个入度为0的点;而出度为0的点(设为n个)无法到达其他点,那么为了使得所有的点连通,需要n条路径从这n个出度为0的点连出。于是,至少需要添加 max(m, n)条边,使得图中所有的点的入度和出度不为0. 
        同时,在一个有向无环图中,如果该图的所有点均可连接到一块,且每个点的出度和入度均不为0,则该图肯定强连通。于是,结果为 max(m,n)

    题意转自:https://www.cnblogs.com/gtarcoder/p/4871267.html

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #define mem(a, b) memset(a, b, sizeof(a))
    using namespace std;
    const int maxn = 150000, INF = 0x7fffffff;
    vector<int> G[maxn];
    int pre[maxn], lowlink[maxn], sccno[maxn];
    int in[maxn], out[maxn];
    int dfs_clock, scc_cnt, n;
    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 calcu()
    {
        int t1 = 0, t2 = 0;
        mem(in, 0);
        mem(out, 0);
        dfs_clock = scc_cnt = 0 ;
        mem(sccno, 0);
        mem(pre, 0);
        for(int i=1; i<=n; i++)
            if(!pre[i])
                dfs(i);
        for(int i=1; i<=n; i++)
            for(int j=0; j<G[i].size(); j++)
                if(sccno[i] != sccno[G[i][j]])
                    out[sccno[i]]++, in[sccno[G[i][j]]]++;
        for(int i=1; i<=scc_cnt; i++)
        {
            if(in[i] == 0)
                t1++;
            if(out[i] == 0)
                t2++;
        }
        if (scc_cnt == 1) printf("1
    0
    ");
        else
            printf("%d
    %d
    ",t1,max(t2,t1));
    
    
    }
    
    int main()
    {
        cin>> n;
        for(int i=1; i<=n; i++)
        {
            for(;;)
            {
                int v;
                cin>> v;
                if(v == 0) break;
                G[i].push_back(v);
    
            }
        }
        calcu();
    
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    Java数据结构与算法(1)
    Ubuntu 19.04 桌面版的安装
    MySQL编程(0)
    CentOS 7.6 系统的安装
    CSharp设计模式读书笔记(24):访问者模式(学习难度:★★★★☆,使用频率:★☆☆☆☆)
    Xshell 5 远程连接工具的安装
    CSharp设计模式读书笔记(23):模板方法模式(学习难度:★★☆☆☆,使用频率:★★★☆☆)
    VMware 12 虚拟机软件的安装
    CSharp设计模式读书笔记(22):策略模式(学习难度:★☆☆☆☆,使用频率:★★★★☆)
    OpenStack-启动实例
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9301096.html
Copyright © 2011-2022 走看看