Redundant Paths |
---|
题意: 给定一个无向连通图,问最少加多少条边可以变成边双连通图。
题解: 将每个边双缩成单个点之后,图上就会剩下一棵树,而最后的答案也就变成了(度数为1的节点个数 + 1)/ 2
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define _for(i, a, b) for(int i = (a); i <= (b); ++i)
const int N = 5e3 + 10;
int n, m;
int cnt, deg[N];
int dfn, low[N];
vector<int> G[N];
void dfs(int u, int fa) {
low[u] = ++dfn;
bool flag = true;
_for(i, 0, G[u].size() - 1) {
int v = G[u][i];
if(v == fa && flag) { flag = false; continue;} //重边的特殊处理
if(!low[v]) dfs(v, u);
low[u] = min(low[u], low[v]);
}
}
int main() {
scanf("%d%d", &n, &m);
while(m--) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
_for(i, 1, n) if(!low[i]) dfs(i, -1);
_for(i, 1, n)
_for(j, 0, G[i].size() - 1){
int v = G[i][j];
if(low[i] != low[v]) deg[low[i]]++;
}
_for(i, 1, n) if(deg[i] == 1) cnt++; //度数为1的节点为叶子节点
printf("%d\n", (cnt + 1) / 2);
return 0;
}