1. 程式人生 > >Redundant Paths POJ - 3177(邊—雙連通分量)

Redundant Paths POJ - 3177(邊—雙連通分量)

clock min algorithm pre tar pat mes 連通 code

題意:

在圖中加邊 看最少能通過加多少條邊把 圖變成邊—雙連通分量

解析:

先做一次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; }

Redundant Paths POJ - 3177(邊—雙連通分量)