ZOJ 2588

求一个无向图的桥(可能存在重边),输出割边的数目,并按顺序输出割边的序号(输入的顺序)。

由于内存的限制 , 无法使用邻接矩阵 , 只能用邻接表了 .

第一次用了邻接表,超内存了;

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <string.h>
 5 using namespace std;
 6 const int N=10002;
 7 const int M=1000002;
 8 struct edge{
 9     int v,next,id,two=0;
10 }e[M];
11 int k,first[M],id,count1;                          //first[i]是以点i为起点的链表头部
12 int dfn[N],low[N],bri[M],mun;
13 void init(){
14     k=1;
15     count1=0;
16     mun=0;
17     id=0;
18     memset(first,0,sizeof(first));
19     memset(low,0,sizeof(low));
20     memset(dfn,0,sizeof(dfn));
21     memset(bri,0,sizeof(bri));
22 }
23 void addedge(int a,int b){                        //向图中加边的算法,注意加上的是有向边//b为a的后续节点既是a---->b
24     int i;
25     for(i=first[a];i;i=e[i].next){
26         if(e[i].v==b)break;
27     }
28     if(i){                                         //方法稍作修改,用来标注重边
29         e[i].two=1;
30         return ;
31     }
32     e[k].v=b;
33     e[k].next=first[a];
34     e[k].id=id;
35     e[k].two=0;
36     first[a]=k++;
37 }
38 void dfs(int u,int far){                           //dfn,Tarjan算法
39     dfn[u]=low[u]=++count1;
40     for(int i=first[u];i;i=e[i].next){
41         int v=e[i].v;
42         if(!dfn[v]){
43             dfs(v,u);
44             low[u]=min(low[u],low[v]);
45             if(low[v]>dfn[u]&&!e[i].two){
46                 bri[mun++]=e[i].id;
47             }
48
49         }
50         else if(v!=far)low[u]=min(low[u],dfn[v]);
51     }
52 }
53 void print(){
54     printf("%d\n",mun);
55     if(mun>0){
56         sort(bri,bri+mun);
57         printf("%d",bri[0]);
58         for(int i=1;i<mun;i++)
59             printf(" %d",bri[i]);
60         printf("\n");
61     }
62 }
63 int main(){
64     int t,n,m,a,b;
65     scanf("%d",&t);
66     while(t--){
67         init();
68         scanf("%d%d",&n,&m);
69         while(m--){
70             scanf("%d%d",&a,&b);
71             id++;
72             addedge(a,b);
73             addedge(b,a);
74         }
75         dfs(1,0);
76         print();
77         if(t)printf("\n");
78     }
79     return 0;
80 }

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
const int N=10002;
const int M=1000002;
struct edge{
    int v,next,id,two=0;
}e[M];
int k,first[M],id,count1;
int dfn[N],low[N],bri[M],mun;
void init(){
    k=1;
    count1=0;
    mun=0;
    id=0;
    memset(first,0,sizeof(first));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(bri,0,sizeof(bri));
}
void addedge(int a,int b){
    int i;
    for(i=first[a];i;i=e[i].next){
        if(e[i].v==b)break;
    }
    if(i){
        e[i].two=1;
        return ;
    }
    e[k].v=b;
    e[k].next=first[a];
    e[k].id=id;
    e[k].two=0;
    first[a]=k++;
}
void dfs(int u,int far){
    dfn[u]=low[u]=++count1;
    for(int i=first[u];i;i=e[i].next){
        int v=e[i].v;
        if(!dfn[v]){
            dfs(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u]&&!e[i].two){
                bri[mun++]=e[i].id;
            }

}
        else if(v!=far)low[u]=min(low[u],dfn[v]);
    }
}
void print(){
    printf("%d\n",mun);
    if(mun>0){
        sort(bri,bri+mun);
        printf("%d",bri[0]);
        for(int i=1;i<mun;i++)
            printf(" %d",bri[i]);
        printf("\n");
    }
}
int main(){
    int t,n,m,a,b;
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d%d",&n,&m);
        while(m--){
            scanf("%d%d",&a,&b);
            id++;
            addedge(a,b);
            addedge(b,a);
        }
        dfs(1,0);
        print();
        if(t)printf("\n");
    }
    return 0;
}

ZOJ 2588,布布扣,bubuko.com

时间: 2024-08-02 06:58:38

ZOJ 2588的相关文章

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

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

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

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

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 求割边问题

题目链接:http://vjudge.net/problem/viewProblem.action?id=14877 题目大意: 要尽可能多的烧毁桥,另外还要保证图的连通性,问哪些桥是绝对不能烧毁的 我们很容易看出不能烧毁的是必然是作为割边存在的桥. 求割边,我们用Tarjan算法,这与求割点有点小区别在与,对于(u,v)的点low[v]>=dfn[u]时就表示u为割点,而low[v]>dfn[u]时才能说明(u,v)是一条割边 因为这里要求出割边的序号,所以在写边的结构体时,用id代表桥的序

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(判断割边)

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

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 割边的求解

题目链接: 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