[bzoj1123] BLO
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 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
题意:
极其简洁啊……
题解:
缩完点双后原图会变为一棵树。
每删掉一个割点,它的子树之间两两不能连接,子树与子树外的点两两不能连接。
然后惊奇的发现这题的点对要算上被删去的那个点。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; }