BZOJ 1123: [POI2008]BLO
1123: [POI2008]BLO
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1030 Solved: 440
[Submit][Status][Discuss]
Description
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
Input
输入n<=100000 m<=500000及m条边
Output
输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。
Sample Input
5 5
1 2
2 3
1 3
3 4
4 5
1 2
2 3
1 3
3 4
4 5
Sample Output
8
8
16
14
8
8
16
14
8
HINT
Source
分析
如果一个点不是割点,那么删去后不会对其他点之间的连通性造成影响;如果是一个割点,影响只和其连接的几个块的大小有关。因此Tarjan求割点的同时注意维护子树大小即可。
代码
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <iostream> 6 #include <algorithm> 7 8 using namespace std; 9 10 #define N 5000000 11 #define LL long long 12 13 int n, m; LL ans[N]; 14 15 int hd[N], to[N], nt[N], tot; 16 17 int dfn[N], low[N], tim; 18 19 int tarjan(int u, int f) 20 { 21 dfn[u] = low[u] = ++tim; ans[u] = (n - 1) << 1; 22 23 int cnt = 0, siz; LL sum = 0, tmp = 0; 24 25 for (int i = hd[u]; ~i; i = nt[i])if (f != to[i]) 26 { 27 if (!dfn[to[i]]) 28 { 29 siz = tarjan(to[i], u); 30 low[u] = min(low[u], low[to[i]]); 31 if (low[to[i]] >= dfn[u]) 32 ans[u] += 2LL * siz * sum, sum += siz; 33 else 34 tmp += siz; 35 } 36 else 37 low[u] = min(low[u], dfn[to[i]]); 38 } 39 40 ans[u] += 2LL * (n - (sum + 1)) * sum; 41 42 return sum + tmp + 1; 43 } 44 45 signed main(void) 46 { 47 scanf("%d%d", &n, &m); 48 49 memset(hd, -1, sizeof(hd)), tot = 0; 50 51 for (int i = 1; i <= m; ++i) 52 { 53 int x, y; scanf("%d%d", &x, &y); 54 55 nt[tot] = hd[x]; to[tot] = y; hd[x] = tot++; 56 nt[tot] = hd[y]; to[tot] = x; hd[y] = tot++; 57 } 58 59 memset(dfn, 0, sizeof(dfn)); tim = 0; tarjan(1, -1); 60 61 for (int i = 1; i <= n; ++i) 62 printf("%lld\n", ans[i]); 63 }
1 #include <cstdio> 2 3 template <class T> 4 inline T min(const T &a, const T &b) 5 { 6 return a < b ? a : b; 7 } 8 9 typedef long long lnt; 10 11 const int mxn = 100005; 12 const int mxm = 1000005; 13 14 int n, m; 15 16 int hd[mxn]; 17 int to[mxm]; 18 int nt[mxm]; 19 20 int dfn[mxn]; 21 int low[mxn]; 22 23 lnt ans[mxn]; 24 25 lnt tarjan(int u, int f) 26 { 27 static int tim = 0; 28 29 ans[u] = (n - 1) << 1; 30 dfn[u] = low[u] = ++tim; 31 32 lnt siz, sum = 0, tmp = 0; 33 34 for (int i = hd[u], v; i; i = nt[i]) 35 if ((v = to[i]) != f) 36 { 37 if (!dfn[v]) 38 { 39 siz = tarjan(v, u); 40 41 low[u] = min(low[u], low[v]); 42 43 if (low[v] >= dfn[u]) 44 ans[u] += 2LL * sum * siz, sum += siz; 45 else 46 tmp += siz; 47 } 48 else 49 low[u] = min(low[u], dfn[v]); 50 } 51 52 ans[u] += 2LL * (n - sum - 1) * sum; 53 54 return sum + tmp + 1; 55 } 56 57 signed main(void) 58 { 59 scanf("%d%d", &n, &m); 60 61 for (int i = 0; i < m; ++i) 62 { 63 static int x, y, tot; 64 65 scanf("%d%d", &x, &y); 66 67 nt[++tot] = hd[x], to[tot] = y, hd[x] = tot; 68 nt[++tot] = hd[y], to[tot] = x, hd[y] = tot; 69 } 70 71 tarjan(1, 0); 72 73 for (int i = 1; i <= n; ++i) 74 printf("%lld\n", ans[i]); 75 }
@Author: YouSiki