每个点只能访问一次,可以将每个点拆成两个点,中间连一条费用为0、容量为1的边。这样求最小费用最大流时就保证了每个点只访问一次。
因为是两艘船走,所以限制流量为2,求出最小费用即可。注意点数会翻倍,数组也要多开一倍大。
Run Time: 0.046s
#define UVa "LT11-9.1658.cpp" //Admiral
#include
#include
#include
#include
#include
#include
using namespace std;
//Global Variables.
const int maxn = 2000 + 5, INF = 1<<30;
int v, e;
////
struct Edge {
int from, to, cap, flow, weight;
Edge(int a, int b, int c, int d): from(a), to(b), cap(c), weight(d), flow(0) {}
};
struct MCMF {
vector edges;
vector G[maxn];
int a[maxn], p[maxn], inq[maxn], d[maxn];
void addEdge(int from, int to, int cap, int weight) {
edges.push_back(Edge(from, to, cap, weight));
edges.push_back(Edge(to, from, 0, -weight));
G[from].push_back(edges.size()-2);
G[to].push_back(edges.size()-1);
}
void init() {
edges.clear();
for(int i = 0; i < maxn; i ++) G[i].clear();
}
bool bellmanFord(int s, int t, int& flow, long long& cost) {
memset(inq, 0, sizeof(inq));
for(int i = 0; i < maxn; i ++) d[i] = INF;
inq[s] = 1;
d[s] = 0;
a[s] = INF;
queue q;
q.push(s);
while(!q.empty()) {
int x = q.front(); q.pop();
inq[x] = 0;
for(int i = 0; i < G[x].size(); i ++) {
Edge& e = edges[G[x][i]];
int y = e.to;
if(e.cap > e.flow && d[y] > d[x] + e.weight) {
d[y] = d[x] + e.weight;
p[y] = G[x][i];
a[y] = min(a[x], e.cap-e.flow);
if(!inq[y]) { q.push(y); inq[y] = 1; }
}
}
}
if(d[t] == INF) {
return false;
}
for(int u = t; u != s; u = edges[p[u]].from) {
edges[p[u]].flow += a[t];
edges[p[u]^1].flow -= a[t];
}
cost += (long long)d[t]*(long long)a[t];
flow += a[t];
return true;
}
int mincostMaxflow(int s, int t, long long& cost) {
int flow = 0;
cost = 0;
while(flow < 2 && bellmanFord(s, t, flow, cost));
return flow;
}
};
int main() {
while(scanf("%d%d", &v, &e) != EOF) {
MCMF mcmf;
mcmf.init();
for(int i = 2; i < v; i ++)
mcmf.addEdge(i, i+v, 1, 0);
int a, b, c;
for(int i = 0; i < e; i ++) {
scanf("%d%d%d", &a, &b, &c);
int from = (a==1)?a:a+v, to = b;
mcmf.addEdge(from, to, 1, c);
}
long long cost = 0;
mcmf.mincostMaxflow(1, v, cost);
cout<