题意:给你一个图,问至少需要加多少条路使得整个图成为边双连通。
求出割边并缩点,可以得到一棵树,统计树上所有度为1的点数,最后的答案就是(cnt+1)/2,这个画个图就明白了。
ps:这题坑了我两个wa,输入和输出原来不需要Sample Input 1。。太坑了
#include <stdio.h> #include <string.h> const int maxn = 1002; const int maxm = 1005; struct EDGE{ int to, next, vis; }edge[maxm<<1]; int head[maxn], dfn[maxn], belo[maxn], low[maxn], st[maxn]; int E, time, top, gtot, type; struct GEDGE{ int u, to; }gedge[maxm]; void newedge(int u, int to) { edge[E].to = to; edge[E].next = head[u]; edge[E].vis = 0; head[u] = E++; } void init() { memset(head, -1, sizeof(head)); memset(dfn, 0, sizeof(dfn)); memset(belo, 0, sizeof(belo)); E = time = type = top = gtot = 0; } int min(int a, int b) { return a > b ? b : a; } void dfs(int u) { dfn[u] = low[u] = ++time; st[++top] = u; for(int i = head[u];i != -1;i = edge[i].next) { if(edge[i].vis) continue; edge[i].vis = edge[i^1].vis = 1; int to = edge[i].to; if(!dfn[to]) { dfs(to); low[u] = min(low[u], low[to]); if(low[to] > dfn[u]) { type++; int v; do { v = st[top--]; belo[v] = type; } while(v != to); gedge[gtot].u = u; gedge[gtot++].to = to; } } else low[u] = min(low[u], low[to]); } } int ans ; void DFS(int u, int pre) { int tot = 0; if(pre != -1) tot++; for(int i = head[u];i != -1;i = edge[i].next) { int to = edge[i].to; if(to != pre) { DFS(to, u); tot++; } } if(tot == 1) ans++; } char s[111]; int main() { int n, m, i, u, to; while(scanf("%d%d", &n, &m) != -1) { init(); for(i = 0;i < m;i ++) { scanf("%d%d", &u, &to); newedge(u, to); newedge(to, u); } for(i = 1;i <= n; i++) if(!dfn[i]) dfs(i); memset(head, -1, sizeof(head)); E = 0; for(i = 0;i < gtot; i++) { u = belo[gedge[i].u]; to = belo[gedge[i].to]; newedge(u, to); newedge(to, u); } ans = 0; DFS(0, -1); printf("%d\n", (ans+1)/2); } return 0; }