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. 使用Python,字标注及最大熵法进行中文分词

    使用Python,字标注及最大熵法进行中文分词 在前面的博文中使用python实现了基于词典及匹配的中文分词,这里介绍另外一种方法, 这种方法基于字标注法,并且基于最大熵法,使用机器学习方法进行训练, ...

  2. javascript笔记3之数据类型

    /* var box = 250; //十进制整型 alert(box); var box = 070; //八进制,按照十进制输出是56 alert(box); var box = 0x1f; // ...

  3. 又一编辑神器-百度编辑器-Ueditor

    (Lionden<hsdlionden@gmail.com> 转载说明) 前段时间发表过一篇关于“KindEditor在JSP中使用”的博文.这几天在沈阳东软进行JavaWeb方面的实习工 ...

  4. Hive MapJoin

    摘要 MapJoin是Hive的一种优化操作,其适用于小表JOIN大表的场景,由于表的JOIN操作是在Map端且在内存进行的,所以其并不需要启动Reduce任务也就不需要经过shuffle阶段,从而能 ...

  5. 曾经的足迹——对Linux CAN驱动的理解(1)

    在Ti的AM335X系列Cortext-A8芯片中,CAN模块采用D_CAN结构,实质即两路CAN接口. 在此分享一下对基于AM335X的Linux CAN驱动源码的理解.下面来分析它的驱动源码及其工 ...

  6. unity3d 学习笔记(一)

    操作:按下shit 点击坐标轴中心 切换透视图 动画烘焙的概念:相当于把原来的控制器动画或者IK(骨骼)动画所有塌陷为逐帧动画,导出的时候必须选这一项 着色器:从技术的角度来看,着色器是渲染器的一个部 ...

  7. Android万能分辨率适应法

    (1)获取屏幕的尺寸 WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); D ...

  8. SqlBulkCopy的一个例子

    public bool InsertAll(IList<NewStockLuoPan> list) { DataTable dt = new DataTable(); dt.Columns ...

  9. SQLSERVER内核架构剖析 (转)

    我们做管理软件的,主要核心就在数据存储管理上.所以数据库设计是我们的重中之重.为了让我们的管理软件能够稳定.可扩展.性能优秀.可跟踪排错. 可升级部署.可插件运行,我们往往研发自己的管理软件开发平台. ...

  10. 将html导出到excel或word

    本质是将html写成word或excel支持的html格式. 如何将html写成word或excel支持的格式? 只需打开计算机上任意一个word或excel文档,打开文件->另存为,选择文件类 ...