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;
}