题目链接:http://vjudge.net/problem/viewProblem.action?id=14877

题目大意:

要尽可能多的烧毁桥,另外还要保证图的连通性,问哪些桥是绝对不能烧毁的

我们很容易看出不能烧毁的是必然是作为割边存在的桥。

求割边,我们用Tarjan算法,这与求割点有点小区别在与,对于(u,v)的点low[v]>=dfn[u]时就表示u为割点,而low[v]>dfn[u]时才能说明(u,v)是一条割边

因为这里要求出割边的序号,所以在写边的结构体时,用id代表桥的序号,我们每次得到a,b总会添加两条边a->b和b->a,因为这是无向图,所以这两条边公用一个id

另外要注意的是这道题目允许两个地点有多条边出现,所以我们需要用一个tag标志位来注明是否有重边

oid addPath(int a,int b,int c)
{
    int i;
    for(i=first[a];i!=-1;i=path[i].next)
        if(path[i].y==b) break;
    if(i!=-1)//说明是重边
        path[i].tag=1;
    else{
        path[k].y=b,path[k].tag=0,path[k].next=first[a],path[k].id=c;
first[a]=k;
        k++;
    }
}

每次深度搜索一个节点,不断更新上面的low值和dfn值,并找到low[v]>dfn[u]的边并将它们保存到bridge数组中,nbridge用来统计桥的数量

void dfs(int u,int fa)
{
    visit[u]=1,dfn[u]=low[u]=tmpdfn++;
    for(int i=first[u];i!=-1;i=path[i].next){
        int j=path[i].y;

if(!visit[j]){
            dfs(j,u);
            low[u]=min(low[j],low[u]);
            if(low[j]>dfn[u]&&!path[i].tag)
                bridge[++nbridge]=path[i].id;
        }
        else{
            if(j!=fa) low[u]=min(low[u],dfn[j]);//j已被访问且不是父亲节点,说明可以形成一条回边
        }
    }
}

总代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 10005
#define M 100005
int tmpdfn,k,nbridge,bridge[M],visit[N],dfn[N],low[N];
int first[N];
struct Path{
int y,tag,id;
int next;
}path[*M]; void addPath(int a,int b,int c)
{
int i;
for(i=first[a];i!=-;i=path[i].next)
if(path[i].y==b) break;
if(i!=-)//说明是重边
path[i].tag=;
else{
path[k].y=b,path[k].tag=,path[k].next=first[a],path[k].id=c;
first[a]=k;
k++;
}
} void dfs(int u,int fa)
{
visit[u]=,dfn[u]=low[u]=tmpdfn++;
for(int i=first[u];i!=-;i=path[i].next){
int j=path[i].y; if(!visit[j]){
dfs(j,u);
low[u]=min(low[j],low[u]);
if(low[j]>dfn[u]&&!path[i].tag)
bridge[++nbridge]=path[i].id;
}
else{
if(j!=fa) low[u]=min(low[u],dfn[j]);//j已被访问且不是父亲节点,说明可以形成一条回边
}
}
}
int main()
{
int T,n,m,x,y;
scanf("%d",&T); while(T--){
scanf("%d%d",&n,&m);
k=,nbridge=,tmpdfn=;
memset(first,-,sizeof(first));
memset(visit,,sizeof(visit));
memset(bridge,,sizeof(bridge));
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
addPath(x,y,i);
addPath(y,x,i);
}
dfs(,);
printf("%d\n",nbridge);
sort(bridge+,bridge+nbridge+);
for(int i=;i<nbridge;i++) printf("%d ",bridge[i]);
if(nbridge>) printf("%d\n",bridge[nbridge]);
if(T>) printf("\n");
}
return ;
}

ZOJ 2588 求割边问题的更多相关文章

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

    题目地址:ZOJ 2588 由于数组开小了而TLE了..这题就是一个求无向连通图最小割边.仅仅要推断dfn[u]是否<low[v],由于low指的当前所能回到的祖先的最小标号,增加low[v]大 ...

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

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

  3. ZOJ 2588 Burning Bridges (tarjan求割边)

    题目链接 题意 : N个点M条边,允许有重边,让你求出割边的数目以及每条割边的编号(编号是输入顺序从1到M). 思路 :tarjan求割边,对于除重边以为中生成树的边(u,v),若满足dfn[u] & ...

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

    模板题——求割点与桥 题意,要使一个无向图不连通,输出必定要删掉的边的数量及其编号.求桥的裸题,可拿来练手. 套模板的时候注意本题两节点之间可能有多条边,而模板是不判重边的,所以直接套模板的话,会将重 ...

  5. [学习笔记]tarjan求割边

    上午打模拟赛的时候想出了第三题题解,可是我不会求割边只能暴力判割边了QAQ 所以,本文介绍求割边(又称桥). 的定义同求有向图强连通分量. 枚举当前点的所有邻接点: 1.如果某个邻接点未被访问过,则访 ...

  6. 【NOIP训练】【Tarjan求割边】上学

    题目描述 给你一张图,询问当删去某一条边时,起点到终点最短路是否改变. 输入格式 第一行输入两个正整数,分别表示点数和边数.第二行输入两个正整数,起点标号为,终点标号为.接下来行,每行三个整数,表示有 ...

  7. HDU 4738——Caocao's Bridges——————【求割边/桥的最小权值】

     Caocao's Bridges Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  8. POJ3694(求割边)

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7943   Accepted: 2893 Descripti ...

  9. tarjan求割边割点

    tarjan求割边割点 内容及代码来自http://m.blog.csdn.net/article/details?id=51984469 割边:在连通图中,删除了连通图的某条边后,图不再连通.这样的 ...

随机推荐

  1. android开发学习 ------- json数据与实体类之间的相互转换

    在网络请求的时候,会返回给我们实体类,我们需要将实体类转化为json字符串,方便处理数据: 有时候也会将json数据转换为实体类. 在Android Studio中,json要互相转换,需要用到gso ...

  2. c#自定义鼠标形状

    更改鼠标指针,需要使用到 Windows API: 1. 添加命名空间的引用: using System.Runtime.InteropServices; using System.Reflectio ...

  3. Koa--基于Node.js平台的下一代web开发框架的安装

    koa 是由 Express 原班人马打造的,致力于成为一个更小.更富有表现力.更健壮的 Web 框架. 使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函 ...

  4. js深拷贝与浅拷贝的区别及实现

    1. 对于基本数据类型 其值在内存中占据着固定大小的空间,并被保存在栈内存中.当一个变量向另一个变量复制基本类型的值,会创建这个值的副本,并且我们不能给基本数据类型的值添加属性.其为深拷贝. 2. 对 ...

  5. C#调用dll(Java方法)

    因为工作需求,要求用C#直接调用Java方法,下面呢是操作过程以及一些理解,如果有什么理解不对的,欢迎大家指出! 具体操作: 一.将Java写好的Demo以jar包形式导出 package demo; ...

  6. 洛谷 P2866 [USACO06NOV]糟糕的一天Bad Hair Day

    题目描述 Some of Farmer John's N cows (1 ≤ N ≤ 80,000) are having a bad hair day! Since each cow is self ...

  7. 如何使用SAP CRM Marketing Survey创建一个市场问卷调查

    使用事务码CRM_SURVEY_SUITE进行编辑.选中Activities这个应用类型,点击新建按钮: 双击Survey的根节点,点击编辑按钮维护Suvey的标题: Survey的正文布局类型(La ...

  8. ZGC,一个超乎想象的垃圾收集器

    Z Garbage Collector,即ZGC,是一个可伸缩的.低延迟的垃圾收集器,主要为了满足如下目标进行设计: 停顿时间不会超过10ms 停顿时间不会随着堆的增大而增大(不管多大的堆都能保持在1 ...

  9. TensorFlow低阶API(四)—— 图和会话

    简介 TensorFlow使用数据流图将计算表示为独立的指令之间的依赖关系.这可生成低级别的编程模型,在该模型中,您首先定义数据流图,然后创建TensorFlow会话,以便在一组本地和远程设备上运行图 ...

  10. uva10366 Faucet Flow

    每次找到两边离中心最高的板,如果等,再找外围的最高版...画图便于理解两边先找到距离(-1,1)最近的最大值L和R,因为可能存在多个最高的挡板.接着比较两个L和R的大小,相等的话分别分析两边,取最小值 ...