poj1236 Network of Schools Tarjian算法

Posted 文竹balala

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1236 Network of Schools Tarjian算法相关的知识,希望对你有一定的参考价值。

终于把Tarjian算法看懂了。

但是遇到某个贴别题目时还是没有思路,看完题解后自己敲有有了好几处BUG,WA的我泪流满面啊,原来就是把某处的一个变量写错了

题意:

 一些学校连成了网络, 在学校之间存在某个协议:每个学校都维护一张传送表,表明他们要负责将收到的软件传送到表中的所有学校。如果A在B的表中,那么B不一定在A的表中。

    现在的任务就是,给出所有学校及他们维护的表,问1、如果所有学校都要被传送到,那么需要几份软件备份;2、如果只用一份软件备份,那么需要添加几条边?

分析:可以先用Tarjian算法求出强连通分量,然后进行缩点,然后重新建图,对第一问求出入度为0的点即可,对第二问,为入读为0的点数和出度为0的点数的最大值,这个结论目前还不太懂,以后要注意灵活运用啊 ,100个点用邻接矩阵够了


#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>

using namespace std;
int n, cnt, tim, top;
const int maxn = 100 + 5;
int a[maxn][maxn], vis[maxn], dfn[maxn], low[maxn];
int in[maxn], out[maxn], belong[maxn], instack[maxn];


void dfs(int u)

    vis[u] = 1;
    dfn[u] = low[u] = tim;//dfn[i]表示访问该点的最早时间
    tim++;               //low[i]表示从节点i出发能够到达的点的开始最早的时间
    instack[++top] = u;//对于访问过的节点入栈
    for (int i = 1; i <= n; i++)
    
        if (!a[u][i]) continue;
        if (!vis[i])//如果没访问过子节点,向下搜,然后更新     
        
            dfs(i);
            low[u] = min(low[u], low[i]);
        
        else if (vis[i] == 1)low[u] = min(low[u], dfn[i]);
                    //如果已经访问过了,并且在栈中,说明u可达的最早节点是i
    
    if (dfn[u] == low[u])//栈里u以上的就是一个强连通分量
    
        int tmp;
        do
        
            tmp = instack[top--];
            belong[tmp] = cnt;//缩点
            vis[tmp] = 2;//出栈
        
        while (tmp != u);
        cnt++;
    


void Init()

    memset(a, 0, sizeof(a));
    memset(vis, 0, sizeof(vis));
    memset(low, 0, sizeof(low));
    memset(dfn, 0, sizeof(dfn));
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    memset(instack, 0, sizeof(instack));
    tim = 1;
    top = 0;
    cnt = 1;

int main()


    //freopen("input.txt", "r", stdin);
    while (cin >> n)
    
        Init();
        for (int i = 1; i <= n; i++)
        
            int  x;
            while (scanf("%d", &x) == 1 && x)
            
                a[i][x] = 1;
            
        
        for (int i = 1; i <= n; i++)
        
            if (!vis[i])dfs(i);
        
        for (int i = 1; i <= n; i++)
        
            for (int j = 1; j <= n; j++)
            
                if (a[i][j] && belong[i] != belong[j])
                
                    out[belong[i]]++;
                    in[belong[j]]++;
                
            
        
        int t1 = 0, t2 = 0;
        for (int i = 1; i < cnt; i++)
        
            if (in[i] == 0)t1++;//入读为0的数量
            if (out[i] == 0)t2++;//出度为0的数量
        
        if (cnt == 2)
        
            printf("1\\n0\\n");
        
        else 
            cout << t1 << endl;
            cout << max(t1, t2) << endl;
        
    
    return 0;




以上是关于poj1236 Network of Schools Tarjian算法的主要内容,如果未能解决你的问题,请参考以下文章

poj1236Network of Schools Tarjan裸题

[POJ1236]Network of Schools(并查集+floyd,伪强连通分量)

POJ1236Network of Schools(强连通分量 + 缩点)

POJ 1236 Network of Schools —— (缩点的应用)

POJ 1236 Network of Schools(tarjan算法 + LCA)

poj1236 Network of Schools Tarjian算法