Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10442 Accepted Submission(s): 2891
Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Changjiang river, and based on those islands, Caocao's army could easily attack Zhou Yu's troop. Caocao also built bridges connecting islands. If all islands were connected by bridges, Caocao's army could be deployed very conveniently among those islands. Zhou Yu couldn't stand with that, so he wanted to destroy some Caocao's bridges so one or more islands would be seperated from other islands. But Zhou Yu had only one bomb which was left by Zhuge Liang, so he could only destroy one bridge. Zhou Yu must send someone carrying the bomb to destroy the bridge. There might be guards on bridges. The soldier number of the bombing team couldn't be less than the guard number of a bridge, or the mission would fail. Please figure out as least how many soldiers Zhou Yu have to sent to complete the island seperating mission.
There are no more than 12 test cases.
In each test case:
The first line contains two integers, N and M, meaning that there are N islands and M bridges. All the islands are numbered from 1 to N. ( 2 <= N <= 1000, 0 < M <= N2 )
Next M lines describes M bridges. Each line contains three integers U,V and W, meaning that there is a bridge connecting island U and island V, and there are W guards on that bridge. ( U ≠ V and 0 <= W <= 10,000 )
The input ends with N = 0 and M = 0.
For each test case, print the minimum soldier number Zhou Yu had to send to complete the mission. If Zhou Yu couldn't succeed any way, print -1 instead.
3 3
1 2 7
2 3 4
3 1 4
3 2
1 2 7
2 3 4
0 0
-1
4
题意:有n个点,由m条边连接,每个边都有一个权值,破坏一个权值最小的边,使得整个图不连通。
思路:明显的tarjan算法求桥的问题,总所周知(学过离散的都知道),桥:删除这条边,使得整个连通图连通分支数增加,也就是删除了桥,使得原本联通的图变得不再联通。那我们只需要找到所有的桥,取其中权值最小者即可,没有桥说明无法破坏整个图,输出-1,否则输出这个权值。
不过呢,不过这里有两个特殊情况:1、如果原来这个图不连通,那就不用派人去了,输出0 ,2、如果破坏的那个边的权值为0,说明这个边上没有人,那我们也需要派遣一个人去安置炸弹。
下面说一下tarjan算法:
1、两个重要的数组:
dfn[i]: i的时间戳(表示每个点的被访问次序),在dfs的时候一旦遇到一个点,那就记录这个点的dfn[],并且不再改变
low[i]: 的子树中的最小时间戳
2、操作方法:
1)我们第一次更新到某一点u的时候,执行dfn[u] = low[u] = ++id; 初始化这两个数据
2)随后我们访问点x的所有子树,并标记u到其子树的路径为已走,无向图的话,就将两条边都记为已走,表示不可往回走,我们一般这样执行:edge[i].use = edge[i ^ 1].use = true;
3)执之后每访问完一个子树v,行 low[u] = min(low[u], low[v]); ,记录u的子树子树中的最小时间戳
4)在访问子树的时候,如果这个子树的根结点v已经被访问了,那么执行 low[u] = min(low[u], dfn[v]); dfn[v] 表示最v树中的最小时间戳了,这样也是统计u的子树中的最小时间戳。
5)如果dfn[u] < low[v] ,说明u的子树的最小时间戳不会低于或等于u,此时u->v 之间的边为一个桥,记录下来
3、实现原理
之前一直说时间戳,但是这个概念不是很明确(我觉得吧),在这里,我们可以把时间戳理解为某一结点被访问的时间,先访问的结点,时间戳 dfn[] 就越小,我们记 u -> v 有边,如果出现了 low[v] <= dfn[u] ,这说明 v 在访问其子树的时候,访问到了 u 或者u之前的结点,说明存在回路 u -> v- > u 或者u 的父节点 ->u,表示成环,此时u->v定然不是桥,相对地,如果 low[v] > dfn[u] ,此时表示 v 的子树中不会访问到u或者u的父节点,此时,如果我们删除了 u-> v 这条边,u的子树v不再和u所在的图相连,因此边 u->v 就是桥了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include