题意:
在图中加边 看最少能通过加多少条边把 图变成边—双连通分量
解析:
先做一次dfs,不同的连通分量的low是不同的 注意重边
缩点
统计度为1的点 那么需要加的边为(ret+1)/2
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <stack> #define mem(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 5005, INF = 0x7fffffff; int dfn[maxn], low[maxn], drgee[maxn]; bool graph[5005][5005]; int dfs_clock, n, m, ret; vector<int> G[maxn]; void init() { for(int i=0; i<=n; i++) G[i].clear(); ret = 0; dfs_clock = 0; mem(low, 0); mem(dfn, 0); mem(drgee, 0); mem(graph, 0); } void tarjan(int u, int fa) { dfn[u] = low[u] = ++dfs_clock; for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; if(!dfn[v]) { tarjan(v, u); low[u] = min(low[u], low[v]); } else if(v != fa) { low[u] = min(low[u], dfn[v]); } } } int main() { while(cin>> n >> m){ init(); for(int i=0; i<m; i++) { int u, v; cin>> u >> v; if(!graph[u][v]) { graph[u][v] = graph[v][u] = 1; G[u].push_back(v); G[v].push_back(u); } } tarjan(1, -1); for(int i=1; i<=n; i++) for(int j=0; j<G[i].size(); j++) if(low[i] != low[G[i][j]]) drgee[low[i]]++; for(int i=0; i<=n; i++) if(drgee[i] == 1) ret++; cout<< (ret+1)/2 <<endl; } return 0; }
原文地址:https://www.cnblogs.com/WTSRUVF/p/9304299.html
时间: 2024-10-09 21:42:32