HDU 3691 Nubulsa Expo

题目

http://acm.hdu.edu.cn/showproblem.php?pid=3691

题意

给一个无向图,给定源点和边的流量,求找到一个汇点使最大流最小

解法

无向图最小割,小红书模版
注意重边,建图时应为每条边权值的累加和

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 310;
const int INF = 0x3f3f3f3f;
int n, map[N][N], b[N], dist[N], m, source;
int min_cut_phase(int ph, int& x, int& y) {
    int i, j, t;
    b[t = 1] = ph;
    for(i = 1; i <= n; i++) {
        if(b[i] != ph)
            dist[i] = map[1][i];
    }
    for(i = 1; i < n; i++) {
        x = t;
        for(t = 0, j = 1; j <= n; ++j) {
            if(b[j] != ph && (!t || dist[j] > dist[t]))
                t = j;
        }
        b[t] = ph;
        for(j = 1; j <= n; j++) {
            if(b[j] != ph)
                dist[j] += map[t][j];
        }
    }
    return y = t, dist[t];
}
void merge(int x, int y) {
    int i ;
    if(x > y)
        swap(x, y);
    for(i = 1; i <= n; i++) {
        if(i != x && i != y)
            map[i][x] += map[i][y], map[x][i] += map[i][y];
    }
    if(y == n)
        return ;
    for(i = 1; i < n; i++) {
        if(i != y) {
            swap(map[i][y], map[i][n]);
            swap(map[y][i], map[n][i]);
        }
    }
}
int min_cut() {
    int i, ret = INF, x, y;
    memset(b, 0, sizeof(b));
    for(i = 1; n > 1; ++i, --n) {
        ret = min(ret, min_cut_phase(i, x, y));
        merge(x, y);
    }
    return ret;
}
int main() {
    int u, v, w;
    while(scanf("%d%d%d", &n, &m, &source) && n) {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n ; j++)
                map[i][j] = 0;
        }
        for(int i = 0; i < m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            map[u][v] += w;
            map[v][u] += w;
        }
        printf("%d\n", min_cut());
    }
    return 0;
}

Source

2010 Asia Fuzhou Regional Contest

posted @ 2015-08-13 10:10  ACM_Record  阅读(136)  评论(0编辑  收藏  举报