Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
标签:ring splay discuss memory ref center src ++ efi
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
输入n<=100000 m<=500000及m条边
输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。
如果一个点不是割点,那么删去后不会对其他点之间的连通性造成影响;如果是一个割点,影响只和其连接的几个块的大小有关。因此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 }
@Author: YouSiki
标签:ring splay discuss memory ref center src ++ efi
原文地址:http://www.cnblogs.com/yousiki/p/6091587.html