ZOJ-2753

Min Cut (Destroy Trade Net)

Time Limit: 15 Seconds      Memory Limit: 32768 KB

Given an undirected graph, in which two vertexes can be connected by multiple edges, what is the min-cut of the graph? i.e. how many edges must be removed at least to partition the graph into two disconnected sub-graphes?

Input

Input contains multiple test cases. Each test case starts with two integers N and M (2<=N<=500, 0<=M<=N*(N-1)/2) in one line, where N is the number of vertexes. Following are M lines, each line contains M integers A, B and C (0<=A,B<N, A<>B, C>0), meaning that there C edges connecting vertexes A and B.

Output

There is only one line for each test case, which is the min-cut of the graph. If the graph is disconnected, print 0.

Sample Input

3 3
0 1 1
1 2 1
2 0 1
4 3
0 1 1
1 2 1
2 3 1
8 14
0 1 1
0 2 1
0 3 1
1 2 1
1 3 1
2 3 1
4 5 1
4 6 1
4 7 1
5 6 1
5 7 1
6 7 1
4 0 1
7 3 1

Sample Output

2
1
2
/**
    最大流 == 最小割 
**/
#include <iostream>
#include <string.h>
#include <cmath>
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 505;
const ll maxw = 1000007;
const ll inf = 1e17;
ll g[N][N], w[N];
int a[N], v[N], na[N];
ll mincut(int n) {
    int i, j, pv, zj;
    ll best = inf;
    for(i = 0; i < n; i ++) {
        v[i] = i;
    }
    while(n > 1) {
        for(a[v[0]] = 1, i = 1; i < n; i ++) {
            a[v[i]] = 0;
            na[i - 1] = i;
            w[i] = g[v[0]][v[i]];
        }
        for(pv = v[0], i = 1; i < n; i ++) {
            for(zj = -1, j = 1; j < n; j ++)
                if(!a[v[j]] && (zj < 0 || w[j] > w[zj])) {
                    zj = j;
                }
            a[v[zj]] = 1;
            if(i == n - 1) {
                if(best > w[zj]) {
                    best = w[zj];
                }
                for(i = 0; i < n; i ++) {
                    g[v[i]][pv] = g[pv][v[i]] += g[v[zj]][v[i]];
                }
                v[zj] = v[--n];
                break;
            }
            pv = v[zj];
            for(j = 1; j < n; j ++) if(!a[v[j]]) {
                    w[j] += g[v[zj]][v[j]];
                }
        }
    }
    return best;
}
int main()
{
    int n, m, s;
    while(~scanf("%d %d", &n, &m))
    {
        for(int i = 0; i <= n; i++)
        {
            for(int j = 0; j <= n; j++)
            {
                g[i][j] = 0;
            }
        }
        int u, v, w;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            // u--;
            // v--;
            g[u][v] += w;
            g[v][u] += w;
        }
        printf("%lld
", mincut(n));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chenyang920/p/4725829.html