ZOJ 2588 求桥的数量

点击打开链接

题意:将无向图中的桥找出来,并将他们的输入序号输出

思路:模版找桥,但是注意处理重边和后面的输出,别的没什么了,模版题

#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=20010;
struct edge{
    int to,id,num;
    edge(int a,int b,int c){to=a;id=b;num=c;}
};
vector<edge>G[maxn];
int L[maxn],E[maxn],ans[maxn],vis[maxn];
int n,m,k,kk;
void dfs(int x,int fa){
    vis[x]=1;L[x]=k;E[x]=k++;
    for(unsigned int i=0;i<G[x].size();i++){
        edge e=G[x][i];
        if(!vis[e.to]){
            dfs(e.to,x);
            L[x]=min(L[x],L[e.to]);
            if(L[e.to]>E[x]&&e.num==0) ans[kk++]=e.id;
        }else if(e.to!=fa) L[x]=min(L[x],E[e.to]);
    }
}
int tarjan(){
    k=0;kk=0;dfs(1,1);
    return kk;
}
int main(){
    int T,a,b,flag;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<maxn;i++){
            G[i].clear();vis[i]=0;
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            flag=0;
            for(unsigned int j=0;j<G[a].size();j++){
                edge e=G[a][j];
                if(e.to==b){
                    G[a][j].num=1;flag=1;
                    for(unsigned int l=0;l<G[b].size();l++){
                        edge ee=G[b][l];
                        if(ee.to==a) G[b][l].num=1;
                    }
                }
            }
            if(flag==0){
                G[a].push_back(edge(b,i,0));
                G[b].push_back(edge(a,i,0));
            }
        }
        int ans1=tarjan();
        printf("%d\n",ans1);
        sort(ans,ans+kk);
        for(int i=0;i<kk-1;i++) printf("%d ",ans[i]);
        if(kk>0) printf("%d\n",ans[kk-1]);
        if(T) printf("\n");
    }
    return 0;
}
时间: 2024-10-13 16:31:30

ZOJ 2588 求桥的数量的相关文章

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

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

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(无向图求割边)

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

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

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

求一个无向图的桥(可能存在重边),输出割边的数目,并按顺序输出割边的序号(输入的顺序). 由于内存的限制 , 无法使用邻接矩阵 , 只能用邻接表了 . 第一次用了邻接表,超内存了: 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <string.h> 5 using namespace std; 6 const int N=10002; 7 const i

ZOJ 2588 Burning Bridges(强连通分量)

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

hdu2460 poj3694 求桥 + 求lca

http://poj.org/problem?id=3694 题意: 给定一个图,对这个图进行加边,求出每加一条边后,图中桥的个数. 思路: 首先肯定是要先求出原图中桥的个数,并且把桥标记起来.思考加一条边以后桥的数量会减少多少,联想到之前的那道题,就是加一条边,能够使桥的数量最少是多少.之前那个做法就是缩点后树的直径,这个就是可以减少的最多的桥的数量.因为如果这是一条链,将两个端点连起来,这上面的桥都消失了.. 所以按照这个思路,可以考虑,对于每个要加的边,求出他们的lca,在这个路径上如果碰