题目大意:给定一个n个点的连通的无向图,一个点的“鸽子值“定义为将它从图中删去后连通块的个数,求每个点的“鸽子值“
解题思路:双连通分量的裸题。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 10010
#define M 100010
struct Edge{
int to, next;
}E[M];
struct Node{
int id, times;
}node[N];
int head[N], pre[N];
int n, m, tot, dfs_clock;
bool cmp(const Node &a, const Node &b) {
if (a.times == b.times)
return a.id < b.id;
return a.times > b.times;
}
int dfs(int u, int fa) {
int lowu = pre[u] = ++dfs_clock;
int child = 0;
for (int i = head[u]; i != -1; i = E[i].next) {
int v = E[i].to;
if (!pre[v]) {
child++;
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if (lowv >= pre[u]) {
node[u].times++;
}
}
else if(pre[v] < pre[u] && v != fa) {
lowu = min(lowu, pre[v]);
}
}
if (fa < 0 && child == 1)
node[u].times = 1;
return lowu;
}
void solve() {
for (int i = 0; i < n; i++) {
node[i].id = i;
node[i].times = 1;
pre[i] = 0;
}
dfs_clock = 0;
dfs(0, -1);
sort(node, node + n, cmp);
for (int i = 0; i < m; i++)
printf("%d %d\n", node[i].id, node[i].times);
printf("\n");
}
void AddEdge(int from, int to) {
E[tot].to = to;
E[tot].next = head[from];
head[from] = tot++;
}
void init() {
memset(head, -1, sizeof(head));
tot = 0;
int u, v;
while (scanf("%d%d", &u, &v) && u >= 0) {
AddEdge(u, v);
AddEdge(v, u);
}
}
int main() {
while (scanf("%d%d", &n, &m) != EOF && n + m) {
init();
solve();
}
return 0;
}