In the war, the intelligence about the enemy is very important. Now, our troop has mastered the situation of the enemy's war zones, and known that these war zones can communicate to each other directly or indirectly through the network. We also know the enemy is going to build a new communication line to strengthen their communication network. Our task is to destroy their communication network, so that some of their war zones can't communicate. Each line has its "cost of destroy". If we want to destroy a line, we must spend the "cost of destroy" of this line. We want to finish this task using the least cost, but our enemy is very clever. Now, we know the network they have already built, but we know nothing about the new line which our enemy is going to build. In this condition, your task is to find the minimum cost that no matter where our enemy builds the new line, you can destroy it using the fixed money. Please give the minimum cost. For efficiency, we can only destroy one communication line.

Input

The input contains several cases. For each cases, the first line contains two positive integers n, m (1<=n<=10000, 0<=m<=100000) standing for the number of the enemy's war zones (numbered from 1 to n), and the number of lines that our enemy has already build. Then m lines follow. For each line there are three positive integer a, b, c (1<=a, b<=n, 1<=c<=100000), meaning between war zone A and war zone B there is a communication line with the "cost of destroy " c.

Output

For each case, if the task can be finished output the minimum cost, or output ‐1.

Sample Input

3 2
1 2 1
2 3 2
4 3
1 2 1
1 3 2
1 4 3

Sample Output

-1
3

题意: 敌人在N个点间建了M条线路,每条线路都有一个权值,敌人要再建一条线路,己方可以毁掉敌方的一条线路,问己方最少要花多少钱(至少得准备多少钱)才能使

这些点不连通。

解析: 先分离出每个双连通分量(删除双联通分量中的任何一条边还是连通的,没有意义),给每个分量重新编一个号,缩成一个点,在Tarjan算法过程中把桥保存下来。

选一条权值最小的桥,分别从两头出发,找次小的桥。答案就是次小的桥的权值,为甚么是找次小的桥,因为如果敌人是把最小的桥所连的两个连通分量再加一条边,则

必须删次小的桥,如果是其他,则只需要删最小的桥即可。

代码

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
typedef __int64 LL;
const int INF=1e9+;
const double eps=1e-;
const int maxn=;
const int maxm=;
int N,M,eid,id,top;
int scc_id,scc[maxn],dfn[maxn],low[maxn],b[maxn],fa[maxn];
int head[maxn],KK[maxn];
struct edge
{
int v,w,next;
edge(int v=,int w=,int next=-):v(v),w(w),next(next){}
}E[*maxm];
struct node
{
int u,v,w;
node(int u=,int v=,int w=):u(u),v(v),w(w){}
};
vector<node> V;
void init()
{
eid=id=top=scc_id=;
for(int i=;i<=N;i++)
{
head[i]=-;
dfn[i]=low[i]=b[i]=scc[i]=;
fa[i]=i;
}
V.clear();
}
void AddEdge(int u,int v,int w)
{
E[++eid]=edge(v,w,head[u]);
head[u]=eid;
}
void Tarjan(int u)
{
dfn[u]=low[u]=++id;
KK[top++]=u;
bool first=false;
for(int i=head[u];i!=-;i=E[i].next)
{
edge& e=E[i];
int v=e.v,w=e.w;
if(v==fa[u]&&!first){ first=true; continue; }
if(!dfn[v])
{
fa[v]=u;
Tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) V.push_back(node(u,v,w));//这条边是桥
}
else low[u]=min(low[u],dfn[v]);
}
int t;
if(dfn[u]==low[u])
{
scc_id++; //双连通分量
do
{
t=KK[--top];
b[t]=scc_id; //连通分量编号
}while(u!=t);
}
return;
}
int ans;
int FindPath(int u,int pre)
{
int Min=INF,MMin=INF;
for(int i=head[u];i!=-;i=E[i].next)
{
int v=E[i].v,w=E[i].w;
if(v==pre) continue;
int t=FindPath(v,u);
if(t<MMin) MMin=t;
if(w<MMin) MMin=w;
if(Min>MMin) swap(Min,MMin);
}
ans=min(ans,MMin);
return Min;
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
init();
int u,v,w;
for(int i=;i<=M;i++)
{
scanf("%d%d%d",&u,&v,&w);
AddEdge(u,v,w); //建边
AddEdge(v,u,w); //反向边
}
for(int i=;i<=N;i++) if(!dfn[i]) Tarjan(i); //找连通分量 int mindist=INF,picku,pickv,Size=V.size();
eid=;
memset(head,-,sizeof(head));
for(int i=;i<Size;i++) //重新建图
{
node& t=V[i];
int u=t.u,v=t.v,w=t.w;
AddEdge(b[u],b[v],w);
AddEdge(b[v],b[u],w);
if(w<mindist){ mindist=w,picku=b[u],pickv=b[v]; } //权值最小的桥
}
ans=INF;
FindPath(picku,pickv);
FindPath(pickv,picku);
if(ans==INF) printf("-1\n");
else printf("%d\n",ans);
}
return ;
}

Hdu4005-The war(双连通缩点)的更多相关文章

  1. HDU 4005 The war(双连通好题)

    HDU 4005 The war pid=4005" target="_blank" style="">题目链接 题意:给一个连通的无向图.每条 ...

  2. hdu 4612 Warm up 双连通缩点+树的直径

    首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...

  3. 边双连通缩点+树dp 2015 ACM Arabella Collegiate Programming Contest的Gym - 100676H

    http://codeforces.com/gym/100676/attachments 题目大意: 有n个城市,有m条路,每条路都有边长,如果某几个城市的路能组成一个环,那么在环中的这些城市就有传送 ...

  4. POJ 3177 Redundant Paths (边双连通+缩点)

    <题目链接> <转载于 >>>  > 题目大意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新 ...

  5. UVA 10972 RevolC FaeLoN(边-双连通+缩点)

    很好的一道图论题,整整撸了一上午... 题意是给定一个无向图,要求将所有边变为有向边,求最少加入多少条有向边,使得该图强连通?这里先假设一个问题:给定一个无向子图,该子图具有怎样的性质才能使得将其无向 ...

  6. POJ - 3177 Redundant Paths (边双连通缩点)

    题意:在一张图中最少可以添加几条边,使其中任意两点间都有两条不重复的路径(路径中任意一条边都不同). 分析:问题就是最少添加几条边,使其成为边双连通图.可以先将图中所有边双连通分量缩点,之后得到的就是 ...

  7. poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&&缩点】

    Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 503 ...

  8. HDU 4005 The war 双连通分量 缩点

    题意: 有一个边带权的无向图,敌人可以任意在图中加一条边,然后你可以选择删除任意一条边使得图不连通,费用为被删除的边的权值. 求敌人在最优的情况下,使图不连通的最小费用. 分析: 首先求出边双连通分量 ...

  9. UVA-10972 RevolC FaeLoN (边双连通+缩点)

    题目大意:将n个点,m条边的无向图变成强连通图,最少需要加几条有向边. 题目分析:所谓强连通,就是无向图中任意两点可互达.找出所有的边连通分量,每一个边连通分量都是强连通的,那么缩点得到bcc图,只需 ...

随机推荐

  1. window.open和window.close的使用详解

    有时候,我们想通过JS实现一个<a>的新开标签的效果,此时我们想到了window.open方法实现.那么window.open到底应该怎么使用呢?   我们知道window.open可以新 ...

  2. iOS 原生二维码扫描,带扫描框和扫描过程动画

    在代码中使用了相对布局框架Masonry 准备两张图片,一张是扫描边框,一张是扫描时的细线分别命名 scanFrame.png和scanLine.png并提前放入工程 导入相对布局头文件 #defin ...

  3. class 类(4)

    要将类实例化,然后通过实例来调用类的方法(函数).在此,把前面经常做的这类事情概括一下: 方法是类内部定义函数,只不过这个函数的第一个参数是self.(可以认为方法是类属性,但不是实例属性) 必须将类 ...

  4. 完善GDAL与OpenCV间的数据格式转换与影像分块读写

    本博客为原创内容,未经博主允许禁止转载,商用,谢谢. 一.前言 关于GDAL与openCV间的数据格式转换,在我之前的博客中已有简要说明,这里,由于最近工作上经常用到openCV里的函数进行图像处理, ...

  5. Android Notification使用及取消

    //发送通知 NotificationManager manger = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE ...

  6. Oracle SQL ANY和ALL语句

    Oracle的嵌套子查询可以使用Some,Any和All对子查询中返回的多行结果进行处理. Some表示满足其中一个的含义,是用or串起来的比较从句. 例如:SELECT * FROM emp WHE ...

  7. 虚拟机克隆linux系统后需要做的网络设置

    1.vim /etc/sysconfig/network-scripts/ifcfg-eth0删除HWMAC地址行,然后重新分配静态IP/掩码/网关/DNS 2.vim /etc/udev/rules ...

  8. MySQL 一些小知识

    1. 关于多表查询 我的理解:由于MySQL多表查询时表之间的连接是笛卡尔积的方式,所以尽量少使用多表查询,如果使用则使用嵌套语句 例:说明: `tb_notice_message` 表数量百万级别以 ...

  9. node-sqlite3-API-归纳总结

    SQLITE3-API-LIST:API1. new sqlite3.Database(filename,[mode],[callback]) 返回数据库对象并且自动打开和连接数据库 它没有独立打开数 ...

  10. .net framework版本以及服务器部署问题

    自己做了个官网,部署到服务器很多问题,发现targetframework为4.0,但是公司服务器的版本为:2.0.50727,但是公司一个项目用的lambda和linq就没有事,发现这个是3.5支持的 ...