[POJ1236]Network of Schools(并查集+floyd,伪强连通分量)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POJ1236]Network of Schools(并查集+floyd,伪强连通分量)相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem?id=1236
这题本来是个强连通分量板子题的,然而弱很久不写tarjan所以生疏了一下,又看这数据范围觉得缩点这个事情可以用点到点之间的距离来判断不知道群巨兹磁不兹磁……下面弱就给大家搞一发如何用floyd和并查集来缩点……大致的思路就是先floyd跑出所有距离,然后O(n^2)找两两都可达的点,把它们的关系用并查集来维护。接下来O(n)找并查集里的代表元素。这个时候应当特判一下连通块为1的时候。再O(n^2)找出所有单向边,然后更新所有代表元素的出入度,就完事了…完事了…数据太水所以弱的floyd跑过了,以后不能这么投机了QAQ
1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm> 18 #include <iostream> 19 #include <iomanip> 20 #include <cstring> 21 #include <climits> 22 #include <complex> 23 #include <fstream> 24 #include <cassert> 25 #include <cstdio> 26 #include <bitset> 27 #include <vector> 28 #include <deque> 29 #include <queue> 30 #include <stack> 31 #include <ctime> 32 #include <set> 33 #include <map> 34 #include <cmath> 35 36 using namespace std; 37 38 #define fr first 39 #define sc second 40 #define cl clear 41 #define W(a) while(a--) 42 #define pb(a) push_back(a) 43 #define Rint(a) scanf("%d", &a) 44 #define Rll(a) scanf("%I64d", &a) 45 #define Rs(a) scanf("%s", a) 46 #define FRead() freopen("in", "r", stdin) 47 #define FWrite() freopen("out", "w", stdout) 48 #define Rep(i, len) for(int i = 0; i < (len); i++) 49 #define For(i, a, len) for(int i = (a); i < (len); i++) 50 #define Cls(a) memset((a), 0, sizeof(a)) 51 #define Clr(a, x) memset((a), (x), sizeof(a)) 52 #define Full(a) memset((a), 0x7f7f, sizeof(a)) 53 54 const int inf = 0x7f7f7f; 55 const int maxn = 111; 56 int n, m; 57 int in[maxn], out[maxn]; 58 int dp[maxn][maxn]; 59 int pos[maxn], cnt; 60 int pre[maxn]; 61 int belong[maxn]; 62 63 int find(int x) { 64 return x == pre[x] ? x : pre[x] = find(pre[x]); 65 } 66 67 void unite(int x, int y) { 68 x = find(x); 69 y = find(y); 70 if(x != y) pre[x] = y; 71 } 72 73 int main() { 74 // FRead(); 75 int v; 76 while(~Rint(n)) { 77 Cls(in); Cls(out); 78 For(i, 1, n+1) { 79 pre[i] = i; 80 For(j, 1, n+1) dp[i][j] = inf; 81 dp[i][i] = 0; 82 } 83 For(u, 1, n+1) { 84 while(Rint(v)) { 85 if(v == 0) break; 86 dp[u][v] = 1; 87 } 88 } 89 For(k, 1, n+1) 90 For(i, 1, n+1) 91 For(j, 1, n+1) 92 if(dp[i][j] > dp[i][k] + dp[k][j]) 93 dp[i][j] = dp[i][k] + dp[k][j]; 94 For(i, 1, n+1) { 95 For(j, i+1, n+1) { 96 if(dp[i][j] != inf && dp[j][i] != inf) { 97 unite(i, j); 98 } 99 } 100 } 101 For(i, 1, n+1) { 102 int fa = find(i); 103 if(i == fa) pos[cnt++] = i; 104 belong[i] = fa; 105 } 106 if(cnt == 1) { 107 printf("1\n0\n"); 108 continue; 109 } 110 For(i, 1, n+1) { 111 For(j, 1, n+1) { 112 if(i == j) continue; 113 if(belong[i] != belong[j] && dp[j][i] == inf && dp[i][j] != inf) { 114 in[belong[i]]++; 115 out[belong[j]]++; 116 } 117 } 118 } 119 int ans1 = 0, ans2 = 0; 120 Rep(i, cnt) { 121 if(!out[pos[i]]) ans1++; 122 if(!in[pos[i]]) ans2++; 123 } 124 printf("%d\n%d\n", ans1, max(ans1, ans2)); 125 } 126 return 0; 127 }
以上是关于[POJ1236]Network of Schools(并查集+floyd,伪强连通分量)的主要内容,如果未能解决你的问题,请参考以下文章
poj1236Network of Schools Tarjan裸题
[POJ1236]Network of Schools(并查集+floyd,伪强连通分量)
POJ1236Network of Schools(强连通分量 + 缩点)
POJ 1236 Network of Schools —— (缩点的应用)