您的位置:首页 > 其它

HDU 3488--Tour(KM or 费用流)

2016-09-12 23:55 387 查看
因为每个点只能经过一次 所以考虑拆点

这题有坑,有重边。。

KM算法

把一个点拆成入点和出点 入点在X部,出点在Y步。

如果u,v之间有路径,就在X部的u点连接Y部的v点

求完美匹配。

当完美匹配的时候,每个点都有一个入度和一个出度,可知成环。

因为完美匹配求得是最大匹配

记得把每条边权值取相反数

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <bitset>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <map>
#include <set>
#define pk(x) printf("%d\n", x)
using namespace std;
#define PI acos(-1.0)
#define EPS 1E-6
#define clr(x,c) memset(x,c,sizeof(x))
//#pragma comment(linker, "/STACK:102400000,102400000")

typedef long long ll;

const int MAXV = 410;
const int INF = 1<<30;

struct Edge { int to, cap, cost, rev; };
vector<Edge> G[MAXV];
int dist[MAXV], prv[MAXV], pre[MAXV], in[MAXV];
queue<int> que;

void addedge(int from, int to, int cap, int cost) {
G[from].push_back((Edge){to, cap, cost, G[to].size()});
G[to].push_back((Edge){from, 0, -cost, G[from].size()-1});
}

int min_cost_max_flow(int s, int t) { //, int f) {
int res = 0;
int f = 0;
while (1) { //f > 0) {
for (int i = 0; i <= t; ++i) dist[i] = INF, in[i] = 0;
dist[s] = 0;
while (!que.empty()) que.pop();
in[s] = 1;
que.push(s);

while (!que.empty()) {
int u = que.front(); que.pop(); in[u] = 0;
for (int i = 0; i < G[u].size(); ++i) {
Edge &e = G[u][i];
if (e.cap > 0 && dist[e.to] > dist[u] + e.cost) {
dist[e.to] = dist[u] + e.cost;
prv[e.to] = u;
pre[e.to] = i;
if (in[e.to] == 0) {
in[e.to] = 1;
que.push(e.to);
}
}
}
}

if (dist[t] == INF) break; //return -1;

int d = INF; // d = f;
for (int v = t; v != s; v = prv[v]) {
d = min(d, G[prv[v]][pre[v]].cap);
}
f += d;
res += d * dist[t];
for (int v = t; v != s; v = prv[v]) {
Edge &e = G[prv[v]][pre[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}

int Scan() {
int res = 0, flag = 0;
char ch;
if((ch = getchar()) == '-') flag = 1;
else if(ch >= '0' && ch <= '9') res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9')
res = res * 10 + (ch - '0');
return flag ? -res : res;
}

int n, m;
int mp[205][205];
int main()
{
int T = Scan();
while (T--) {
n = Scan(), m = Scan();
int u, v, w;
int src = 0, sink = n*2+1;
for (int i = 0; i <= sink; ++i) G[i].clear();
for (int i = 1; i <= n; ++i) {
addedge(src, i, 1, 0);
addedge(i+n, sink, 1, 0);
}
for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) mp[i][j] = INF;
while (m--) {
u = Scan(), v = Scan(), w = Scan();
mp[u][v] = min(mp[u][v], w);
}
for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) {
if (mp[i][j] != INF) {
addedge(i, j+n, 1, mp[i][j]);
}
}
printf("%d\n", min_cost_max_flow(src, sink));
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: