ZOJ 2588 Burning Bridges(无向图求割边)

ZOJ 2588 Burning Bridges

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2588

题意:给定一个无向图连通图,(其中可能有重边),要求去掉一条边之后,使得整个图不再连通。输出这些符合条件的边的序号。

思路:这就是一个简单的无向图求割边,需要注意的是这个无向图有重边,重边一定不是割边。

代码:

/*=========================================
    无向图求割点和桥
    复杂度:O(E + V)
    割点:
        1:若k为深搜树的根Root,当且仅当k的儿子数(分支数)>=2时k为割点;
        2:若k为搜索树的中间结点(即k既不为根也不为叶),那么k必然有father和son,若low[son]>= dfn[k],则k必然为割点。
    割桥:
        如果low[v] > dfn[u] 则(u,v)为割桥 (需要判断是否有重边,如果有重边一定不是割边)
=========================================*/
/*
ID: [email protected]
PROG:
LANG: C++
*/
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<fstream>
#include<cstring>
#include<ctype.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i < n; i++)
#define per(i, a, n) for (int i = n - 1; i >= a; i--)
#define eps 1e-6
#define debug puts("===============")
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define POSIN(x,y) (0 <= (x) && (x) < n && 0 <= (y) && (y) < m)
typedef long long ll;
typedef unsigned long long ULL;
const int maxn = 11000;
const int maxm = 110000;
int n, m;
struct node {
    int v, id, tot;
    node(int _v, int _id, int _tot) {
        v = _v, id = _id, tot = _tot;
    }
};
vector<node> g[maxn];
int dfn[maxn], low[maxn], vis[maxn], sub[maxn]; //sub记录每个割点分为多少块
bool cut[maxn];
int bridge[maxm], cnt;
void dfs(int u, int f, int dep) {
    vis[u] = 1;
    dfn[u] = low[u] = dep;
    int child = 0;
    for (int i = 0; i < g[u].size(); i++) if (g[u][i].v != f) {
            int v = g[u][i].v;
            if (vis[v] == 1 && dfn[v] < low[u]) low[u] = dfn[v];    //回边更新low值
            if (vis[v] == 0) {
                dfs(v, u, dep + 1);
                child++;
                if (low[v] < low[u]) low[u] = low[v];  //通过儿子回到祖先
                if (low[v] > dfn[u] && g[u][i].tot == 1) bridge[cnt++] = g[u][i].id;
            }
        }
    vis[u] = 2;
}
void cut_bridge() {
    cnt = 0;
    memset(vis, 0, sizeof(int) * (n + 10));
    dfs(1, -1, 0); //i为一个点
    //如果多个连通块,需要对每一个连通块调用dfs
}
int main () {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= n; i++) g[i].clear();
        int u, v;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d", &u, &v);
            bool flag = false;
            for (int j = 0; j < g[u].size(); j++) if (g[u][j].v == v) {
                g[u][j].tot++;
                flag = true;
                break;
            }
            if (flag) for (int j = 0; j < g[v].size(); j++) if (g[v][j].v == u) {
                g[v][j].tot++;
                break;
            }
            if (!flag)
                g[u].pb(node(v, i, 1)), g[v].pb(node(u, i, 1));
        }
        cut_bridge();
        sort(bridge, bridge + cnt);
        printf("%d\n", cnt);
        rep(i, 0, cnt) printf("%d%c", bridge[i], i == cnt - 1 ? '\n' : ' ');
        if (T > 0) puts("");
    }
    return 0;
}
时间: 2024-08-01 22:35:41

ZOJ 2588 Burning Bridges(无向图求割边)的相关文章

ZOJ 1588 Burning Bridges (tarjan求割边)

题目链接 题意 : N个点M条边,允许有重边,让你求出割边的数目以及每条割边的编号(编号是输入顺序从1到M). 思路 :tarjan求割边,对于除重边以为中生成树的边(u,v),若满足dfn[u] < low[v],则边(u,v)是割边. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace st

ZOJ 2588 Burning Bridges(判断割边)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2588 题意: Ferry王国是一个漂亮的岛国,一共有N个岛国.M座桥,通过这些桥可以从每个小岛都能 到达任何一个小岛.很不幸的是,最近Ferry王国被Jordan征服了.Jordan决定烧毁所有的桥. 这是个残酷的决定,但是Jordan的谋士建议他不要这样做,因为如果烧毁所有的桥梁,他自己的 军队也不能从一个岛到达另一个岛.因此Jordan决定烧尽可能多的桥,只

ZOJ 2588 Burning Bridges 求无向图桥 边双连通裸题

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 binshen的板子: #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #i

【求无向图的桥,有重边】ZOJ - 2588 Burning Bridges

模板题——求割点与桥 题意,要使一个无向图不连通,输出必定要删掉的边的数量及其编号.求桥的裸题,可拿来练手. 套模板的时候注意本题两节点之间可能有多条边,而模板是不判重边的,所以直接套模板的话,会将重边也当做桥输出,因此要在判断桥的时候加一个判断,即当且仅当两点之间仅有一条边,且满足dfn[cur] < low[i],(cur, i)才是桥. 另外本题节点数为105,用邻接矩阵的话会内存超限,所以我用了了一个multiset存储边及其编号. 代码如下: 1 #include<cstdio>

ZOJ 2588 Burning Bridges(无向连通图求割边)

题目地址:ZOJ 2588 由于数组开小了而TLE了..这题就是一个求无向连通图最小割边.仅仅要推断dfn[u]是否<low[v],由于low指的当前所能回到的祖先的最小标号,增加low[v]大于dfn[u]时,说明v无法通过其它边回到u之前的点.也就是说v假设想要回到u的祖先点.必需要经过u点,那这条边非常明显就是一条割边.这题还要去重边,假如有重边的话.说明怎么销毁哪条边总能通过还有一条边,所以仅仅要有重边.说明这两点之间没有割边. 代码例如以下: #include <iostream&g

zoj 2588 Burning Bridges【双连通分量求桥输出桥的编号】

Burning Bridges Time Limit: 5 Seconds      Memory Limit: 32768 KB Ferry Kingdom is a nice little country located on N islands that are connected by M bridges. All bridges are very beautiful and are loved by everyone in the kingdom. Of course, the sys

ZOJ 2588 Burning Bridges(强连通分量)

题目地址:ZOJ 2588 因为数组开小了而TLE了..这题就是一个求无向连通图最小割边.只要判断dfn[u]是否<low[v],因为low指的当前所能回到的祖先的最小标号,加入low[v]大于dfn[u]时,说明v无法通过其他边回到u之前的点,也就是说v如果想要回到u的祖先点,必须要经过u点,那这条边很明显就是一条割边.这题还要去重边,假如有重边的话,说明怎么销毁哪条边总能通过另一条边,所以只要有重边,说明这两点之间没有割边. 代码如下: #include <iostream> #in

ZOJ 2588 Burning Bridges 割边的求解

题目链接: ZOJ2588 题意: 给出一个无向的连通图,问去掉图中的哪些边,都会使图将不连通 题解思路: 割边的求解: 1.需要用到Tarjan算法的框架,首先求出dfn low 两个数组 当递归返回时  判断dfn[u]和low[v]的关系 只有当dfn[u]  < low[v]  的情况下u-v是一条割边(u是关节点 ,且u-v不含重边,即dfn[u] != low[v]) 2.题目中还有出现重边的情况  重边是不可能成为割边的  我们需要对重边进行标记 代码: #include<ios

HDU 4738——Caocao&#39;s Bridges——————【求割边/桥的最小权值】

Caocao's Bridges Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4738 Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army st