[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 —— (缩点的应用)

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

poj1236 Network of Schools Tarjian算法