1. 程式人生 > >[POI 2008] BLO

[POI 2008] BLO

tps inline ans bit c++ 搜索 class code sum

[題目鏈接]

https://www.lydsy.com/JudgeOnline/problem.php?id=1123

[算法]

首先,如果一個點不是割點,那麽,去掉該點後不連通的有序點對就為 : 2 * (n - 1)

否則,去掉這個點後,這個圖就被分為了 :

1. 這個點本身

2. 這個點在搜索樹上的一些子樹

3. 除1,2這兩部分的節點

我們可以通過乘法原理算出答案,詳見代碼

[代碼]

#include<bits/stdc++.h>
using
namespace std; #define MAXN 100010 #define MAXM 500010 struct edge { int to,nxt; } e[MAXM << 1]; int i,n,m,x,y,timer,tot; int size[MAXN],dfn[MAXN],low[MAXN],head[MAXN]; long long ans[MAXN]; bool visited[MAXN],is_cut[MAXN]; inline void addedge(int u,int v) { tot++; e[tot] = (edge){v,head[u]}; head[u]
= tot; } inline void tarjan(int u) { int i,v,cnt,sum; size[u] = 1; dfn[u] = low[u] = ++timer; visited[u] = true; cnt = sum = 0; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (!visited[v]) { tarjan(v); size[u]
+= size[v]; low[u] = min(low[u],low[v]); if (dfn[u] <= low[v]) { sum += size[v]; cnt++; ans[u] += 1ll * size[v] * (n - size[v]); low[u] = min(low[u],low[v]); if (u != 1 || cnt > 1) is_cut[u] = true; } } else low[u] = min(low[u],dfn[v]); } if (!is_cut[u]) ans[u] = 2 * (n - 1); else ans[u] += 1ll * (n - 1) + 1ll * (n - sum - 1) * (sum + 1); } int main() { scanf("%d%d",&n,&m); for (i = 1; i <= m; i++) { scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } tarjan(1); for (i = 1; i <= n; i++) printf("%lld\n",ans[i]); return 0; }

[POI 2008] BLO