POI 2008, BLO B城市
// 222 POI 2008, BLO.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
http://oj.daimayuan.top/course/23/problem/986
有n个点m条边无向连通图的图,保证没有重边和自环。对于每个点,输出将这个点的所有边删除之后,有多少点对不能互相连通。
这里的点对是有顺序的,也就是(u,v)和(v,u)需要被统计两次。
输入格式
第一行包含两个数n,m(1≤n≤105,1≤m≤5×105)。
接下来m行,每行两个整数u,v表示一条无向边。
输出格式n行,每行一个整数,表示答案。
样例输入
5 5
1 2
2 3
1 3
3 4
4 5
样例输出
8
8
16
14
8
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010, M = 1000010;
int h[N], e[M], ne[M], idx;
int n, m, root;
int dfn[N], low[N], timestamp;
bool cut[N];
int sz[N];
long long ans[N];
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++timestamp;
int flag = 0; long long res = 0;
sz[u] = 1; long long sum = 0;
for (int i = h[u]; i != -1; i = ne[i]) {
int k = e[i];
if (!dfn[k]) {
tarjan(k);
sz[u] += sz[k];
low[u] = min(low[u], low[k]);
if (low[k] >= dfn[u]) {
flag++;
res += sum * sz[k]*2;
sum += sz[k];
if (u != root || flag > 1) cut[u] = true;
}
}
else {
low[u] = min(low[u], dfn[k]);
}
}
if (cut[u]) {
res += 2 * (n - 1);
res += (n - sum - 1) * (sum) * 2;
}
else {
res = 2 * (n - 1);
}
ans[u] = res;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m;
for (int i = 0; i < m; i++) {
int a, b; cin >> a >> b;
add(a, b); add(b, a);
}
int root = 1;
tarjan(root);
for (int i = 1; i <= n; i++) {
cout << ans[i] << endl;
}
return 0;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
浙公网安备 33010602011771号