ZOJ 2588 Burning Bridges 求割边
注意:去掉反向边

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define maxn 10004 #define maxm 100055 #define inf 1000000000 int min(int a, int b) { return a < b ? a : b; } struct E { int v, next; }edge[maxm<<1]; int head[maxn], tot; int n, m; void add(int s, int t) { edge[tot].v = t; edge[tot].next = head[s]; head[s] = tot++; edge[tot].v = s; edge[tot].next = head[t]; head[t] = tot++; } int low[maxn], dfn[maxn]; int ans[maxn]; int num; void init() { tot = 0; num = 0; memset(head, -1, sizeof(head)); memset(dfn, 0, sizeof(dfn)); } int id; void dfs(int u, int fa) { low[u] = dfn[u] = ++id; int i, v; bool flag = 0; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(!flag && v == fa) { flag = 1; continue; } // 注意:去掉一条反向边, 其它的边可能是重边 if(!dfn[v]) { dfs(v, u); low[u] = min(low[u], low[v]); if(low[v] > dfn[u]) ans[num++] = i; // 边的编号 } else low[u] = min(low[u], dfn[v]); } } int main() { int i, j, cas; int x, y; scanf("%d", &cas); while(cas--) { scanf("%d%d", &n, &m); init(); while(m--) { scanf("%d%d", &x, &y); add(x, y); } dfs(1, -1); printf("%d\n", num); if(num) { sort(ans, ans+num); for(i = 0; i < num-1; i++) printf("%d ", ans[i]/2+1); printf("%d\n", ans[i]/2+1); } if(cas) puts(""); } return 0; }