poj3177--Redundant Paths(边的双连通)
有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走。现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指:没有公共边的路,但可以经过同一个中间顶点。
一个连通无向图最少加几条边变成双连通图
(缩点后叶子节点(即度数为1)的个数 + 1) / 2
#include <iostream> #include <cstdio> #include <cstring> using namespace std; /* 一个连通无向图最少加几条边变成双连通图 边的双连通 (缩点后叶子节点(即度数为1)的个数 + 1)/2 */ const int N = 5005; const int M = 200005; struct Edge { int to, next; bool cut; } edge[M]; int cnt_edge; int head[N]; void add_edge(int u, int v) { edge[cnt_edge].to = v; edge[cnt_edge].next = head[u]; edge[cnt_edge].cut = false; head[u] = cnt_edge++; } int dfn[N]; int idx; int low[N]; int stk[N]; int top; int kind[N]; int cnt; bool in[N]; int bridge; int n, m; void tarjan(int u, int pre) { low[u] = dfn[u] = ++idx; in[u] = true; stk[++top] = u; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (v == pre) continue; if (!dfn[v]) { tarjan(v, u); low[u] = min(low[u], low[v]); if (low[v] > dfn[u]) { bridge++; edge[i].cut = true; edge[i ^ 1].cut = true; } } else low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { cnt++; int v; do { v = stk[top--]; in[v] = false; kind[v] = cnt; } while (u != v); } } int deg[N]; void solve() { for (int u = 1; u <= n; ++u) { for (int i = head[u]; i != -1; i = edge[i].next) { if (edge[i].cut) deg[kind[u]]++; } } int leaf = 0; for (int i = 1; i <= cnt; ++i) if (deg[i] == 1) ++leaf; printf("%d\n", (leaf + 1) / 2); } void init() { memset(head, -1, sizeof head); memset(dfn, 0, sizeof dfn); memset(deg, 0, sizeof deg); top = idx = cnt = cnt_edge = 0; } int main() { int a, b; while (~scanf("%d%d", &n, &m)) { init(); for (int i = 0; i < m; ++i) { scanf("%d%d", &a, &b); add_edge(a, b); add_edge(b, a); } tarjan(1, -1); solve(); } return 0; }