ZOJ Problem - 2588 Burning Bridges tarjan算法求割边

  题意:求无向图的割边。

  思路:tarjan算法求割边,访问到一个点,如果这个点的low值比它的dfn值大,它就是割边,直接ans++(之所以可以直接ans++,是因为他与割点不同,每条边只访问了一遍)。

  需要注意的就是此处有多重边,题目中要求输出确定的不能被删除的边,而多重边的保留不是可以确定的,所以多重边都是不可以被保留的,我们可以在邻接表做一个flag的标记,判断他是不是多重边。

  注意建图的时候数组应该是m × 2,因为这里是无向边,当心RE!

  注意输出的时候编号是必须要拍好序再输出。

  还有一个地方需要注意的就是应该选择高效的建图方式,我一开始看见给了5秒,就用邻接矩阵建了图,毕竟他能很好的记录重边,但交上去并不好使。。。又换了vector,结果莫名其妙的程序崩溃,我都开始怀疑人生了,想到zoj一向以严格刁钻出名,干脆换了比较高效的链式前向星,总算是过了,下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 10010
int head[maxn],tot,dfn[maxn],low[maxn],ans_id[maxn*10],ans,cnt;
struct EDGE
{
    int to,nxt,flag,id;
} edge[maxn*20];
void add_edge(int x,int y,int id)
{
    bool mark = true;
    int pos = 0;
    for(int i = head[x]; i != -1; i = edge[i].nxt)
    {
        if(edge[i].to == y)
        {
            mark = false;
            pos = i;
            break;
        }
    }
    if(!mark)
    {
        edge[pos].flag = 1;
        return;
    }
    edge[cnt].to = y;
    edge[cnt].nxt = head[x];
    edge[cnt].flag = 0;
    edge[cnt].id = id;
    head[x] = cnt++;
}
void tarjan(int x,int fa)
{
    dfn[x] = low[x] = ++tot;
    for(int i = head[x]; i != -1; i = edge[i].nxt)
    {
        int y = edge[i].to;
        if(!dfn[y])
        {
            tarjan(y,x);
            low[x] = min(low[x],low[y]);
            if(low[y] > dfn[x] && !edge[i].flag)///判断重边
            {
                ans_id[ans++] = edge[i].id;
            }
        }
        else if(y != fa)
            low[x] = min(low[x],dfn[y]);
    }
    return;
}
int main()
{
    int t,n,m;
    scanf("%d",&t);
    while(t--)
    {
        cnt = 0,tot = 0,ans = 0;
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= m; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add_edge(x,y,i);
            add_edge(y,x,i);
        }
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        tarjan(1,-1);
        printf("%d\n",ans);
        sort(ans_id,ans_id + ans);
        if(ans != 0)
        {
            for(int i = 0; i < ans; i++)
            {
                i == 0 ? printf("%d",ans_id[i]) : printf(" %d",ans_id[i]);
            }
            printf("\n");
        }
        if(t)
            puts("");
    }
    return 0;
}
时间: 2024-12-26 13:45:39

ZOJ Problem - 2588 Burning Bridges tarjan算法求割边的相关文章

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

ZOJ 2588 Burning Bridges 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2588 题意:给定一个无向图连通图,(其中可能有重边),要求去掉一条边之后,使得整个图不再连通.输出这些符合条件的边的序号. 思路:这就是一个简单的无向图求割边,需要注意的是这个无向图有重边,重边一定不是割边. 代码: /*========================================= 无向图求割点

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 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

CF:Problem 427C - Checkposts强连通Tarjan算法

这题昨晚做了,刚开始看题的时候没想出好法子,然后就看D题了,一看D题发现是后缀数组,然后就把模板改了点就交了上去--不幸的是--WA了,然后重新看题,果然题目看漏了--不仅要用后缀数组和前缀数组求出公共子缀,还要是求最小的,而且在每个串里都不能重复的,这下就想了会不会了,然后看见大帝C过了,然后就重新回来看C了,看了会终于明天怎么做了. C题意:给个图,然后每个点都有权值,求最小的花费及方案数:最小的花费是这样的:因为是建立一个岗哨,然后这个岗哨可以管哪些呢,可以管 i = j 的,或者可以从

HDU 1269 迷宫城堡 tarjan算法求强连通分量

基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等,那这个点就在一个强连通分量里面,此时从栈中向外取出元素,知道取出的元素与这个点的值相等时结束,我们所有取出的点与这个点在同一个强连通分量里.下面是代码,其实代码里本来不需要id数组记录点属于哪个强连通分量的,因为题目没有做要求,但是为了保留模板完整还是带着了,以供以后复习使用. #include<c

图论算法(6)(更新版) --- Tarjan算法求强连通分量

之前Tarjan算法求强连通分量博文中,代码实现用到了固定大小数组,扩展起来似乎并不是很方便,在java里这样来实现本身就是不太妥当的,所以下面给出一个更新版本的代码实现: package test; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util

CF:Problem 427C - Checkposts强连通 Tarjan算法

tarjan算法第一题 喷我一脸....把手写栈的类型开成了BOOL,一直在找错... #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define maxn 100005 const int MOD=1000000007; using namespace std; struct node { int to,next; }edge[maxn*3]; int

Tarjan算法求有向图强连通分量并缩点

// Tarjan算法求有向图强连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> using namespace std; const int N = 100010, M = 1000010; // int ver[M], Next[M], head[N],

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