【bzoj1123】BLO
阿新 • • 發佈:2018-11-06
1123: [POI2008]BLO
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2222 Solved: 1090
[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 51 2
2 3
1 3
3 4
4 5
Sample Output
88
16
14
8
HINT
Source
題意:
極其簡潔啊……
題解:
縮完點雙後原圖會變為一棵樹。
每刪掉一個割點,它的子樹之間兩兩不能連線,子樹與子樹外的點兩兩不能連線。
然後驚奇的發現這題的點對要算上被刪去的那個點。GG。
程式碼:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define MAXN 100005 #define MAXM 500005 #define INF 0x7fffffff #define ll long long ll hd[MAXN],to[MAXM<<1]; ll nxt[MAXM<<1],siz[MAXN]; ll dfn[MAXN],low[MAXN]; ll N,M,ans[MAXN],cnt,num; inline ll read(){ ll x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar())if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } inline void tarjan(ll u){ dfn[u]=low[u]=++num; ll cutnum=0;siz[u]=1; for(ll i=hd[u];i;i=nxt[i]){ ll v=to[i]; if(dfn[v]) low[u]=min(low[u],dfn[v]); else{ tarjan(v);siz[u]+=siz[v]; low[u]=min(low[u],low[v]); if(dfn[u]<=low[v]){ ans[u]+=(cutnum*siz[v]); cutnum+=siz[v]; } } } ans[u]+=(cutnum*(N-cutnum-1)); return; } inline void addedge(ll u,ll v){ to[++cnt]=v,nxt[cnt]=hd[u]; hd[u]=cnt;return; } int main(){ N=read(),M=read(); for(ll i=1;i<=M;i++){ ll u=read(),v=read(); addedge(u,v),addedge(v,u); } for(ll i=1;i<=N;i++) if(!dfn[i]) tarjan(i); for(ll i=1;i<=N;i++) printf("%lld\n",ans[i]*2+(N-1)*2); return 0; }