无向图的割边
割边:若在连通图中删除某条边,图不再连通,则删除的边为割边。
根据low[i],和dfn[i]的n定义,我们知道,若(u,v)是生成树的一条边,且low[v] > dfn[u],则(u,v)为割边------桥。
zoj 2588 题意:
给n个顶点,m条边, 可能有重边。问你图中有几个桥?并按顺序输出桥的编号。
#include<cstdio> #include<cstring> #include<algorithm> #define _Clr(x, y) memset(x, y, sizeof(x)) #define INF 0x3f3f3f3f #define N 200050 using namespace std; struct Node //弧结构 { int to; int num, next; }edge[N]; int head[N], tot; int dfn[N], low[N]; int bridge[N]; bool used[N]; int n, cnt, ght; // 分别记录顶点数,深度优先数,割边数。 void Init() { cnt=ght=tot=0; _Clr(head, -1); _Clr(dfn, 0); _Clr(used, 0); } void Add_edge(int a, int b, int id) { edge[tot].to = b; edge[tot].num = id; edge[tot].next = head[a]; head[a] = tot++; edge[tot].to = a; edge[tot].num = id; edge[tot].next = head[b]; head[b] = tot++; } void dfs(int u, int f) { dfn[u]=low[u]=++cnt; used[u] = true; for(int i=head[u]; i!=-1; i=edge[i].next) { int v = edge[i].to; if(!dfn[v]) { dfs(v, edge[i].num); low[u] = min(low[u], low[v]); if(low[v] > dfn[u]) bridge[++ght] = edge[i].num; } else if(edge[i].num != f && used[v]) low[u] = min(low[u], dfn[v]); } } void Tarjan() { dfs(1, -1); sort(bridge+1, bridge+ght+1); printf("%d\n", ght); for(int i=1; i<=ght; i++) printf("%d%s", bridge[i], i==ght?"\n":" "); } int main() { int T, m, a, b; scanf("%d", &T); while(T--) { Init(); scanf("%d%d", &n, &m); for(int i=1; i<=m; i++) { scanf("%d%d", &a, &b); Add_edge(a, b, i); } Tarjan(); if(T) puts(""); } return 0; }