zoukankan      html  css  js  c++  java
  • poj 1236 Network of Schools(tarjan缩点)

    题目链接:http://poj.org/problem?id=1236

    题意:给出n个学校和一些学校之间的网络链接关系,学校之间的网络是单向边,让你求出两个问题的答案,1.至少需要多少份软件,使得所有学校都可以收到。2.如果希望用一份软件就能够使所有学校收到需要添加几条边

    题解:首先求强连通分量然后缩点,所谓缩点就是将一个连通图化为一个点。然后再以联通图构成一个图。

    然后这题的问题1只要求联通分量入度为0的点的和就行了,问题2就是求连通分量入度和出度为0的和的最

    大值。(为了构成全连通分量构成的图联通,最少要加max(入度为0的,出度为0的)才能保证联通)。

    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    using namespace std;
    const int M = 10000 + 10;
    const int N = 100 + 10;
    struct TnT {
        int v , next;
    }edge[M];
    int head[N] , e;
    int Low[N] , DFN[N] , Stack[N] , Belong[N];
    int Index , top;
    int scc;
    bool Instack[N];
    int num[N];
    void init() {
        memset(head , -1 , sizeof(head));
        e = 0;
    }
    void add(int u , int v) {
        edge[e].v = v , edge[e].next = head[u] , head[u] = e++;
    }
    void Tarjan(int u) {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            int v = edge[i].v;
            if(!DFN[v]) {
                Tarjan(v);
                Low[u] = min(Low[u] , Low[v]);
            }
            else if(Instack[v]) Low[u] = min(Low[u] , DFN[v]);
        }
        if(Low[u] == DFN[u]) {
            scc++;
            do {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] = scc;
                num[scc]++;
            }
            while(v != u);
        }
    }
    int In[N] , Out[N];
    int main() {
        int n;
        while(scanf("%d" , &n) != EOF) {
            init();
            for(int i = 1 ; i <= n ; i++) {
                int x;
                while(scanf("%d" , &x)) {
                    if(x == 0) break;
                    add(i , x);
                }
            }
            memset(DFN , 0 , sizeof(DFN));
            memset(Instack , false , sizeof(Instack));
            memset(num , 0 , sizeof(num));
            memset(In , 0 , sizeof(In));
            memset(Out , 0 , sizeof(Out));
            for(int i = 1 ; i <= n ; i++)
                if(!DFN[i]) Tarjan(i);
            for(int i = 1 ; i <= n ; i++) {
                for(int j = head[i] ; j != -1 ; j = edge[j].next) {
                    int v = edge[j].v;
                    if(Belong[i] != Belong[v]) {
                        In[Belong[v]]++;
                        Out[Belong[i]]++;
                    }
                }
            }
            int ans1 = 0 , ans2 = 0;
            for(int i = 1 ; i <= scc ; i++) {
                if(In[i] == 0) ans1++;
                if(Out[i] == 0) ans2++;
            }
            if(scc == 1) printf("1
    0
    ");
            else printf("%d
    %d
    " , ans1 , max(ans1 , ans2));
        }
        return 0;
    }
    
  • 相关阅读:
    python 函数的参数
    python 函数
    python set
    python 字典
    python 条件判断和循环
    OSMC Vs. OpenELEC Vs. LibreELEC – Kodi Operating System Comparison
    深度学习中噪声标签的影响和识别
    Open images from USB camera on linux using V4L2 with OpenCV
    球面镜成像原理,焦距推导
    动画演示10个有趣但毫无用处的Linux命令
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6875680.html
Copyright © 2011-2022 走看看