ZOJ 2588 Burning Bridges 求割边

本文介绍了一种基于深度优先搜索(DFS)的割边检测算法,通过遍历图结构并利用低点值和发现时间来确定哪些边是割边。文章详细展示了如何在邻接表中避免重边,并提供了一个完整的C++实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求割边,实际上跟求割点类似,dfs的过程中就能求出割边,判断条件变为low[v] > dfn[u]和(u,v)不能是重边

我用的邻接表存储,结构体中新增的一个变量,用来判断是否有重边

每次插入边之前先扫描一遍该点的邻接点,看是否已经存在一个边

/* ID: sdj22251 PROG: subset LANG: C++ */ #include <iostream> #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cmath> #include <ctime> #define LOCA #define MAXN 10005 #define INF 100000000 #define eps 1e-7 using namespace std; struct node { int v, w, id; node *next; } edge[MAXN]; int visited[MAXN]; int n, m; int tmpdfn; int dfn[MAXN]; int low[MAXN]; int ans[200005]; int cnt; void dfs(int u, int father) { node *ptr = edge[u].next; while(ptr) { int v = ptr -> v; if(!visited[v]) { visited[v] = 1; tmpdfn++; dfn[v] = low[v] = tmpdfn; dfs(v, u); low[u] = min(low[u], low[v]); if(low[v] > dfn[u] && ptr -> w == 0) { ans[cnt++] = ptr -> id; } } else if(v != father) { low[u] = min(low[u], dfn[v]); } ptr = ptr -> next; } } void init() { low[1] = dfn[1] = 1; tmpdfn = 1; cnt = 0; memset(visited, 0, sizeof(visited)); visited[1] = 1; for(int i = 0; i <= n; i++) { edge[i].w = 0; edge[i].next = NULL; } } void insert(const int &x, const int &y, const int &id) { node *ptr = edge[x].next; bool flag = false; while(ptr) { if(ptr -> v == y) { ptr -> w = 1; flag = true; } ptr = ptr -> next; } if(!flag) { node *pptr = new node; pptr -> v = y; pptr -> id = id; pptr -> w = 0; pptr -> next = edge[x].next; edge[x].next = pptr; } } int main() { int T, x, y, cas = 0; scanf("%d", &T); while(T--) { if(cas++) printf("\n"); scanf("%d%d", &n, &m); init(); for(int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); insert(x, y, i); insert(y, x, i); } dfs(1, 0); printf("%d\n", cnt); sort(ans, ans + cnt); for(int i = 0; i < cnt - 1; i++) printf("%d ", ans[i]); if(cnt) printf("%d\n", ans[cnt - 1]); } return 0; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值