题目:

  曹操在长江上建立了一些点,点之间有一些边连着。如果这些点构成的无向图变成了连通图,那么曹操就无敌了。刘备为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥。但是诸葛亮把所有炸弹都带走了,只留下一枚给刘备。所以刘备只能炸一条桥。

  题目给出n,m。表示有n个点,m条桥。

  接下来的m行每行给出a,b,c,表示a点和b点之间有一条桥,而且曹操派了c个人去守卫这条桥。

  现在问刘备最少派多少人去炸桥。

  如果无法使曹操的点成为多个连通图,则输出-1.

 

思路:

  就是用tarjan算法算出桥的数量,再比较哪一个的值最小。

Tips:

  注意三点:

  ①. 有重边,所以tarjan算法要处理重边。有两种处理方法,一种是先把所有的边存下,发现两点有重边的时候就只给这两个点连一条权值为无穷大的边。或者是在tarjan算法里处理重边,即使之求u或u的子树能够追溯到的最早的栈中节点的次序号时可访问父节点的次序号。

  ②. 如果无向图图本身已经有两个连通图了,就无需派人去炸桥,这时候输出0。

  ③. 如果求出来的最小权值桥的守卫人数为0时,也需要派出一个人去炸桥。

Code:

// tarjan算法求无向图的桥、边双连通分量并缩点
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include <bits/stdc++.h>
#define cls(s,h) memset(s,h,sizeof s)
using namespace std;
const int N = ;
int n, m ;
struct edge
{
int to;
int pre;
int id;
int w;
};
edge E[N*N];
int head[N],tot;
//int soldier[N][N];//第一种方法所需的的邻接矩阵
int low[N],dfn[N],ts,top,st[N],ins[N];
int minn; void init()
{
cls(head,-);
tot=;
//CLR(soldier,INF);
cls(low,);
cls(dfn,);
ts=top=;
cls(ins,);
minn=1e8;
}
inline void add(int s,int t,int w,int id)
{
E[tot].to=t;
E[tot].id=id;
E[tot].w=w;
E[tot].pre=head[s];
head[s]=tot++;
}
void tarjan(int u,int id)
{
low[u]=dfn[u]=++ts;
ins[u]=;
st[top++]=u;
int v;
for (int i=head[u]; ~i; i=E[i].pre)
{
v=E[i].to;
if(id==E[i].id)
continue;
if(!dfn[v])
{
tarjan(v,E[i].id);
low[u]=min<int>(low[v],low[u]);
if(low[v]>dfn[u])
{
int need=E[i].w;
if(need<minn)
minn=need;
}
}
else if(ins[v])
low[u]=min<int>(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
do
{
v=st[--top];
ins[v]=;
}
while (u!=v);
}
} int main()
{
while(scanf("%d%d",&n,&m)&&n+m)
{
init(); //tot = 1;
for (int i = ; i <= m; i++)
{
int x, y,z;
scanf("%d%d%d", &x, &y,&z);
add(x, y,z,i), add(y,x,z,i);
}
int k = ;
minn = 1e8;
for (int i = ; i <= n; i++)
if (!dfn[i]) tarjan(i, -),k++;
//for (int i = 2; i < tot; i += 2)
// if (bridge[i])
// printf("%d %d\n", ver[i ^ 1], ver[i]); // for (int i = 1; i <= n; i++)
// if (!c[i]) {
// ++dcc;
// dfs(i);
// }
//printf("There are %d e-DCCs.\n", dcc);
//for (int i = 1; i <= n; i++)
// printf("%d belongs to DCC %d.\n", i, c[i]); //for (int i = 2; i <= tot; i++) {
// int x = ver[i ^ 1], y = ver[i];
// if (c[x] == c[y]) continue;
// add_c(c[x], c[y]);
// }
//printf("缩点之后的森林,点数 %d,边数 %d\n", dcc, tc / 2); //for (int i = 2; i < tc; i += 2)
//printf("%d %d %d\n", vc[i ^ 1], vc[i],edge[i]);
// minn = min(minn,edge[i]);
if(k > )
minn = ;
else if(minn == )
minn = ;
else if(minn == 1e8)
minn = -;
printf("%d\n",minn); }
return ;
}
// tarjan算法求无向图的桥、边双连通分量并缩点
// 割边判定定理 dfn[x] < low[y]
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include <bits/stdc++.h>
#define cls(s,h) memset(s,h,sizeof s)
using namespace std;
const int N = ;
int n, m ;
struct edge
{
int to;
int pre;
int id;
int w;
};
edge E[N*N];
int head[N],tot;
//int soldier[N][N];//第一种方法所需的的邻接矩阵
int low[N],dfn[N],ts,top,st[N],ins[N];
int minn; void init()
{
cls(head,-);
tot=;
//CLR(soldier,INF);
cls(low,);
cls(dfn,);
ts=top=;
cls(ins,);
minn=1e8;
}
inline void add(int s,int t,int w,int id)
{
E[tot].to=t;
E[tot].id=id;
E[tot].w=w;
E[tot].pre=head[s];
head[s]=tot++;
}
void tarjan(int u,int id)
{
low[u]=dfn[u]=++ts;
ins[u]=;
st[top++]=u;
int v;
for (int i=head[u]; ~i; i=E[i].pre)
{
v=E[i].to;
if(id==E[i].id)
continue;
if(!dfn[v])
{
tarjan(v,E[i].id);
low[u]=min<int>(low[v],low[u]);
if(low[v]>dfn[u])
{
//枚举每一个桥,找到最小的桥
int need=E[i].w;
if(need<minn)
minn=need; }
}
else if(ins[v])
low[u]=min<int>(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
do
{
v=st[--top];
ins[v]=;
}
while (u!=v);
}
} int main()
{
while(scanf("%d%d",&n,&m)&&n+m)
{
init(); //tot = 1;
for (int i = ; i <= m; i++)
{
int x, y,z;
scanf("%d%d%d", &x, &y,&z);
add(x, y,z,i), add(y,x,z,i);
}
int k = ;
minn = 1e8;
for (int i = ; i <= n; i++)
if (!dfn[i]) tarjan(i, -),k++;//连通块数量
if(k > )
minn = ;
else if(minn == )
minn = ;
else if(minn == 1e8)
minn = -;
printf("%d\n",minn); }
return ;
}

更新代码

Hdu 4738【tanjan求无向图的桥】割边判定定理 dfn[x] < low[y]的更多相关文章

  1. Hdu 4738【求无向图的桥】.cpp

    题目: 曹操在长江上建立了一些点,点之间有一些边连着.如果这些点构成的无向图变成了连通图,那么曹操就无敌了.刘备为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥.但是诸葛亮把所有炸弹都带走了,只留下 ...

  2. tarjan算法求无向图的桥、边双连通分量并缩点

    // tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...

  3. hdu 4738 Caocao's Bridges 求无向图的桥【Tarjan】

    <题目链接> 题目大意: 曹操在长江上建立了一些点,点之间有一些边连着.如果这些点构成的无向图变成了连通图,那么曹操就无敌了.周瑜为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥.但是诸 ...

  4. I - Caocao's Bridges - hdu 4738(求桥)

    题意:曹操的船之间有一些桥连接,现在周瑜想把这些连接的船分成两部分,不过他只能炸毁一座桥,并且每座桥上有士兵看守,问,他最少需要排多少士兵去炸桥如果不能做到,输出‘-1’ 注意:此题有好几个坑,第一个 ...

  5. hdu 4738 Caocao's Bridges 图--桥的判断模板

    Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. hdu 4738 Caocao's Bridges(桥的最小权值+去重)

    http://acm.hdu.edu.cn/showproblem.php?pid=4738 题目大意:曹操有一些岛屿被桥连接,每座都有士兵把守,周瑜想把这些岛屿分成两部分,但他只能炸毁一条桥,问最少 ...

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

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

  8. [Tarjan系列] Tarjan算法求无向图的桥和割点

    RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...

  9. Light OJ - 1026 - Critical Links(图论-Tarjan算法求无向图的桥数) - 带详细注释

     原题链接   无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 也可以先用Tajan()进行dfs算出所有点 的low和dfn值,并记录dfs过程中每个 点的父节点:然后再把所有点遍历一遍 ...

随机推荐

  1. HDU 6136 Death Podracing (堆)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6136 题解 完了,普及题都不会做了... 发现一个重要性质是只有相邻的人才会相撞,于是直接拿堆维护即可 ...

  2. B. Chocolates

    B. Chocolates time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  3. 自动化部署脚本--linux执行sh脚本

    自动化部署脚本文件目录: 运行主程序:./install.sh #!/bin/bash SCRIPTPATH=$(cd "$(dirname "$0")"; p ...

  4. Linux如何安装卸载软件

    Linux 中如何卸载已安装的软件. Linux软件的安装和卸载一直是困扰许多新用户的难题.在Windows中,我们可以使用软件自带的安装卸载程序或在控制面板中的“添加/删除程 序” 来实现.与其相类 ...

  5. 微信、QQ第三方登录授权时的问题总结

    一.微信第一个问题:redirect_uri域名与后台配置不一致,错误码:10003 解决方案: 1,首先确定访问的第三方接口地址参数前后顺序是否正确,redirect_uri回调地址是否加了http ...

  6. 【转】C++ const成员变量和成员函数(常成员函数)

    转:http://c.biancheng.net/view/2230.html 在类中,如果你不希望某些数据被修改,可以使用const关键字加以限定.const 可以用来修饰成员变量和成员函数. co ...

  7. python中unicode utf-8的互换

    比较简单明了,直接上例子 # -*- coding: utf-8 -*- t0 = u'测试' #u'\u6d4b\u8bd5' t1 = '测试' #'\xe6\xb5\x8b\xe8\xaf\x9 ...

  8. JavaEE-实验四 HTML与JSP基础编程

    1.使用HTML的表单以及表格标签,完成以下的注册界面(验证码不做) html代码(css写于其中) <!DOCTYPE html> <html> <head> & ...

  9. Screen Painter 程序设计

    一.Screen 的创建及维护, TCode:SE51 输入程序名称,单击[建立], 程序1000为SAP预留屏幕号,屏幕号必须定义1000外的其他数字,且最多不超过四位, 本例定义屏幕为SAP预留屏 ...

  10. java:struts框架5(Converter,Validation,Tags(Object-Graph Navigation Language))

    1.Converter: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTY ...