1123: [POI2008]BLO
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1030 Solved: 440[][][]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
Sample Output
8 8 16 14 8
HINT
Source
分析
如果一个点不是割点,那么删去后不会对其他点之间的连通性造成影响;如果是一个割点,影响只和其连接的几个块的大小有关。因此Tarjan求割点的同时注意维护子树大小即可。
代码
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 8 using namespace std; 9 10 #define N 500000011 #define LL long long12 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 else34 tmp += siz;35 }36 else37 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 #include2 3 template 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 else46 tmp += siz;47 }48 else49 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