poj1236 Network of Schools(tarjan缩点)

来源:互联网 发布:淘宝网店软文范例 编辑:程序博客网 时间:2024/05/19 15:24

题意:一些学校连成了网络, 在学校之间存在某个协议:每个学校都维护一张传送表,表明他们要负责将收到的软件传送到表中的所有学校。如果A在B的表中,那么B不一定在A的表中。现在的任务就是,给出所有学校及他们维护的表,问1、如果所有学校都要被传送到,那么需要几份软件备份;2、如果只用一份软件备份,那么需要添加几条边?

思路:先使用tarjan算法找强连通分量,并进行缩点。对于缩点后的图,求每个点的入度和出度,第1问就是图中入度为0的点的个数,而第2问则是入度为0的点的个数和出度为0的点的个数这两者中较大的那一个。(参考DAG性质:对于一个有向无环图,若想让它成为强连通图,至少需要添加max(a,b) a为入度为0的边点的数量,b为出度为0的点的数量

代码:

#include <iostream>#include <fstream>#include <vector>#include <stack>#include <algorithm>#define MAXN 105using namespace std;vector<int> node[MAXN];stack<int> S;int DFN[MAXN], LOW[MAXN], belong[MAXN], out[MAXN], in[MAXN];bool vis[MAXN];int tot;int cnt;void tarjan(int u){int v;DFN[u] = LOW[u] = ++tot;S.push(u);vis[u] = 1;for (int i = 0; i < node[u].size(); i++){v = node[u][i];if (!DFN[v]){tarjan(v);LOW[u] = min(LOW[u], LOW[v]);}else if(vis[v])LOW[u] = min(LOW[u], DFN[v]);}if (DFN[u] == LOW[u]){cnt++;do {v = S.top();S.pop();vis[v] = 0;belong[v] = cnt;} while (v != u);}}int main(){//fstream cin("test.txt");int n, ans1, ans2;ans1 = ans2 = 0;cin >> n;for (int i = 1; i <= n; i++){int to;while (cin >> to, to)node[i].push_back(to);}for (int i = 1; i <= n; i++){if (!DFN[i])tarjan(i);}for (int i = 1; i <= n; i++)for (int j = 0; j < node[i].size(); j++){//计算出度if (belong[i] != belong[node[i][j]]){out[belong[i]]++;in[belong[node[i][j]]]++;}}for (int i = 1; i <= cnt; i++){if (in[i] == 0)ans1++;if (out[i]== 0)ans2++;}if (cnt == 1)cout << 1 << endl << 0 << endl;else{cout << ans1 << endl;cout << max(ans1, ans2) << endl;}//system("pause");return 0;}


原创粉丝点击