BZOJ 1123: [POI2008]BLO( tarjan )

tarjan找割点..不是割点答案就是(N-1)*2, 是割点的话就在tarjan的时候顺便统计一下 

-------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
 
const int maxn = 100009;
const int maxm = 500009;
 
struct edge {
int to;
edge* next;
} E[maxm << 1], *pt = E, *head[maxn];
 
void add(int u, int v) {
pt->to = v; pt->next = head[u]; head[u] = pt++;
}
void addedge(int u, int v) {
add(u, v); add(v, u);
}
 
edge* Rev(edge* e) {
return E + ((e - E) ^ 1);
}
 
int dfn[maxn], low[maxn], size[maxn], CK = 0, N;
ll ans[maxn];
 
void tarjan(int x, edge* r) {
dfn[x] = low[x] = ++CK;
size[x] = 1;
int cnt = 0;
for(edge* e = head[x]; e; e = e->next) if(e != r) {
if(!dfn[e->to]) {
tarjan(e->to, Rev(e));
if(low[e->to] >= dfn[x])
ans[x] += cnt * size[e->to], cnt += size[e->to];
else
low[x] = min(low[x], low[e->to]);
size[x] += size[e->to];
} else
low[x] = min(low[x], dfn[e->to]);
}
ans[x] += ll(cnt) * (N - cnt - 1);
}
 
void init() {
int m;
scanf("%d%d", &N, &m);
while(m--) {
int u, v; scanf("%d%d", &u, &v);
addedge(--u, --v);
}
}
 
void work() {
memset(ans, 0, sizeof ans);
memset(dfn, 0, sizeof dfn);
memset(low, 0, sizeof low);
for(int i = 0; i < N; i++)
if(!dfn[i]) tarjan(i, NULL);
for(int i = 0; i < N; i++)
printf("%lld\n", 2LL * (ans[i] + N - 1));
}
 
int main() {
init();
work();
return 0;
}

------------------------------------------------------------------------------- 

 

1123: [POI2008]BLO

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 751  Solved: 309
[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

Sample Output

8
8
16
14
8

HINT

Source

 

posted @ 2015-10-20 20:50  JSZX11556  阅读(223)  评论(0编辑  收藏  举报