zoj2588 Burning Bridges --- 寻求尖端

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define eps 1e-6
#define ll __int64
using namespace std;
#define N 10010
#define M 100010

struct node//边结点
{
    int v,tag,id;//v为所连接的还有一个结点。tag为重边数,id为序号
    node *next;
};
int n,m;//点,边数
int nid;//输入时边的序号
node mem[M*2];int memp;//mem为存储边结点的数组,memp为mem数组序号
node *e[N];//邻接表
int brig[M];//brig[i]=1表示第i+1条边为割边
int nbrig;//求得割边的数目
int low[N],dfn[N];//low[i]为顶点i可达祖先的最小编号。dfn[i]为深度优先数
int vis[N];//0未訪问 1已訪问 2已訪问且已检查邻接结点

//在邻接表中插入边(i,j)。若有重边。则仅仅把对应边结点的tag+1
int addedge(int i,int j)
{
    node* p;
    for(p=e[i];p!=NULL;p=p->next)
        if(p->v==j) break;
    if(p!=NULL)
    {
        p->tag++;
        return 0;
    }
    p=&mem[memp++];
    p->v=j;
    p->next=e[i];
    e[i]=p;
    p->id=nid;
    p->tag=0;
    return 1;
}

//參数含义:i为当前搜索的顶点。father为i的父节点。dth为搜索深度
void dfs(int i,int father,int dth)
{
    vis[i]=1;
    dfn[i]=low[i]=dth;
    node* p;
    for(p=e[i];p!=NULL;p=p->next)
    {
        int j=p->v;
        if(j!=father&&vis[j])
            low[i]=min(low[i],dfn[j]);
        if(!vis[j])
        {
            dfs(j,i,dth+1);
            low[i]=min(low[i],low[j]);
            if(low[j]>dfn[i]&&!p->tag)
                brig[p->id]=++nbrig;

        }
    }
    vis[i]=2;
}

void init()
{
    memp=nid=nbrig=0;
    memset(e,0,sizeof e);
    memset(brig,0,sizeof brig);
    memset(vis,0,sizeof vis);
}

int main()
{
    int t,i,j,a,b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            addedge(a-1,b-1);
            addedge(b-1,a-1);
            nid++;
        }
        dfs(0,-1,1);
        printf("%d\n",nbrig);
        for(i=0,j=nbrig;i<m;i++)
        {
           // printf("i:%d brig[i]:%d\n",i+1,brig[i]);
            if(brig[i])
            {
                printf("%d",i+1);
                if(--j) putchar(' ');
            }
        }
        if(nbrig) puts("");
        if(t) puts("");
    }
    return 0;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-08-01 23:09:48

zoj2588 Burning Bridges --- 寻求尖端的相关文章

zoj2588 Burning Bridges --- 求割边

#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define eps 1e-

ZOJ2588 Burning Bridges(割边)

题目要输出一个无向图的所有割边.用Tarjan算法: 一遍DFS,构造出一颗深度优先生成树,在原无向图中边分成了两种:树边(生成树上的边)和反祖边(非生成树上的边). 顺便求出每个结点的DFS序dfn[u] 和 每个结点能沿着它和它的儿子的返祖边达到的结点最小的DFS序low[u]. 一条边(u,v)是割边当且仅当—— low[v]>dfn[u] 注意具体实现时,无向图的边在邻接表中有正反两条边,那么如果一条边是树边了,另一条边不应该是反祖边,要忽略. 1 #include<cstdio>

ZOJ2588.Burning Bridges——边双连通分量,有重边

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 题目描述: 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

Burning Bridges 求tarjan求割边

Burning Bridges 给出含有n个顶点和m条边的连通无向图,求出所有割边的序号. 1 #include <cstdio> 2 #include <cstring> 3 #define clr(a) memset(a,0,sizeof(a)) 4 #define N 10005 5 #define M 100005 6 #define MIN(a,b) ((a)>(b)?(b):(a)) 7 typedef struct NodeStr //边结点 8 { 9 int

xtu summer individual 5 E - Burning Bridges

Burning Bridges Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on ZJU. Original ID: 258864-bit integer IO format: %lld      Java class name: Main Ferry Kingdom is a nice little country located on N islands that are connected by

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

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

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?problemId=1588 binshen的板子: #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #i