题意:在一个无向图中找一个最小汉密顿环,使得环的权值和最小。
难度:3
题解:二分图最优匹配。把每个点i拆成两点Xi和Yi,每次连边就连一条Xi到Yj和一条Xj到Yi的有权值的边,用KM算法求解。
难度:3
题解:二分图最优匹配。把每个点i拆成两点Xi和Yi,每次连边就连一条Xi到Yj和一条Xj到Yi的有权值的边,用KM算法求解。
#include <stdio.h>
#include <string.h>
#define INF (1<<30)
#define N 1003
inline int min(int a, int b) {
return a < b ? a : b;
}
inline int max(int a, int b) {
return a > b ? a : b;
}
struct Edge {
int to, cost, next;
};
int head[N];
Edge edge[20004];
void addEdge (int a, int b, int c, int pos) {
edge[pos].to = b;
edge[pos].cost = c;
edge[pos].next = head[a];
head[a] = pos;
}
int lx[N], ly[N];
bool vx[N], vy[N];
int slash[N], match[N];
bool Hungary(int u) {
vx[u] = true;
for (int k = head[u]; k != -1; k = edge[k].next) {
int v = edge[k].to;
if (vy[v] == false && lx[u] + ly[v] == edge[k].cost) {
vy[v] = true;
if (match[v] == -1 || Hungary(match[v])) {
match[v] = u;
return true;
}
} else {
slash[v] = min(slash[v], lx[u] + ly[v] - edge[k].cost);
}
}
return false;
}
int gao(int n) {
for (int i = 1; i <= n; i++) {
lx[i] = -INF; ly[i] = 0; match[i] = -1;
for (int k = head[i]; k != -1; k = edge[k].next) {
lx[i] = max(lx[i], edge[k].cost);
}
}
for (int k = 1; k <= n; k++) {
while (true) {
for (int i = 1; i <= n; i++) {
vx[i] = vy[i] = false;
slash[i] = INF;
}
if (Hungary(k)) {
break;
}
int d = INF;
for (int i = 1; i <= n; i++) {
if (vy[i] == false) {
d = min(d, slash[i]);
}
}
if (d == INF) {
return -1;
}
for (int i = 1; i <= n; i++) {
if (vx[i]) {
lx[i] -= d;
}
if (vy[i]) {
ly[i] += d;
}
}
}
}
int ret = 0;
for (int i = 1; i <= n; i++) {
int tmp = -INF;
for (int k = head[match[i]]; k != -1; k = edge[k].next) {
if (edge[k].to == i) {
tmp = max(tmp, edge[k].cost);
}
}
ret -= tmp;
}
return ret;
}
int main () {
int T;
int index = 1;
scanf ("%d", &T);
while (T--) {
int n, m;
scanf ("%d %d", &n, &m);
memset(head, -1, sizeof (head));
int ie = 0;
while (m--) {
int a, b, c;
scanf ("%d %d %d", &a, &b, &c);
addEdge(a, b, -c, ie++);
addEdge(b, a, -c, ie++);
}
int ans = gao(n);
printf ("Case %d: ", index++);
if (ans == -1) {
puts("NO");
} else {
printf ("%d\n", ans);
}
}
return 0;
}