1. 程式人生 > >HDU 4738 Caocao's Bridges 求橋 諸葛亮帶著炸彈跑路了

HDU 4738 Caocao's Bridges 求橋 諸葛亮帶著炸彈跑路了

Description

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.

Input

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 <= N 2 )

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.

Output

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.

Sample Input

3 3
1 2 7
2 3 4
3 1 4
3 2
1 2 7
2 3 4
0 0

Sample Output

-1
4

題目翻譯:

這道題就是說求橋,在所有橋裡求權值最小的,其中的權值表示這條路上有多少個敵人,如果有5個敵人,就至少派五個人,但是注意如果沒有敵人,還是需要派一個人去,我們派人去的目的是炸橋,這裡的橋是圖論中定義的橋,如果有多個橋,則派人去敵人防守最少的,也就是權值最小的

題解:

求橋的板子題!!!這道題的程式碼是板子,記得多複習233,求橋有個操作是傳邊,我們可以從u到v再到u,因為有重邊,所以我們傳邊,不走已經走過的邊就可以了

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

const int MAXN = 1000 + 10;
const int MAXM = 1000 * 1000 + 10;
int n, m, cnt, tail, timer;
int head[MAXN], dfn[MAXN], low[MAXN], ans;
bool ARI[MAXN][MAXN];

void init( ) {
    memset( head, 0, sizeof( head) );
    memset( dfn, 0, sizeof( dfn ) );
    memset( low, 0, sizeof( low ) );
    tail = 1; timer = 0; cnt = 0; ans = 0x7fffffff;
}
struct Line{ int to, nxt, flow; }line[MAXM];
void add_line( int from, int to, int flow ) {
    line[++tail].to = to;
    line[tail].nxt = head[from];
    line[tail].flow = flow;
    head[from] = tail; 
}
void Tarjan( int u, int fa ) {
    timer++; low[u] = dfn[u] = timer; cnt++;
    for( register int i = head[u]; i; i = line[i].nxt ) {
        int v = line[i].to;
        if( i == ( fa ^ 1 ) ) continue;
        if( !dfn[v] ) {
            Tarjan( v, i );
            low[u] = min( low[u], low[v] );
            if( low[v] > dfn[u] ) ans = min( ans, line[i].flow );
        } else low[u] = min( low[u], dfn[v] ); 
    }
}
int main( ) {
    while( scanf( "%d%d", &n, &m ) != EOF && n != 0 && m != 0 ) {
        init( );
        for( register int i = 1; i <= m; i++ ) { int u, v, w;
            scanf( "%d%d%d", &u, &v, &w );
            add_line( u, v, w ); add_line( v, u, w );
        }
        Tarjan( 1, -1 );
        if( cnt != n ) { printf( "0\n" ); continue; }
        if( ans == 0x7fffffff ) {
            printf( "-1\n" ); continue;
        } else if( ans == 0 ) printf( "1\n" );
          else                printf( "%d\n", ans );
    }
    return 0;
}

HDU坑題多

這裡寫圖片描述