6 9 1 2 5 2 3 5 3 1 10 3 4 12 4 1 8 4 6 11 5 4 7 5 6 9 6 5 4 6 5 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1
42 -1HintIn the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20 + 22 = 42.
水一遍熟悉熟悉模板。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f
#define maxn 500
#define maxm 77000
using namespace std;
int n, m;
int outset;
int inset;
struct node {
int u, v, cap, flow, cost, next;
};
node edge[maxm];
int head[maxn], cnt;
int per[maxn];//记录增广路径上 到达点i的边的编号
int dist[maxn], vis[maxn];
void init(){
cnt = 0;
memset(head, -1, sizeof(head));
}
void add(int u, int v, int w, int c){
int i;
for(i = head[u]; i != -1; i = edge[i].next){
node E = edge[i];
if(v == E.v)
break;
}
if(i != -1){
if(edge[i].cost > c)
edge[i].cost = c, edge[i ^ 1].cost = -c;
return ;
}
//edge[cnt] = {u, v, w, 0, c, head[u]}这样写就直接超时了。
node E1 = {u, v, w, 0, c, head[u]};
edge[cnt] = E1;
head[u] = cnt++;
node E2 = {v, u, 0, 0, -c, head[v]};
edge[cnt] = E2;
head[v] = cnt++;
}
void getmap(){
outset = 0;
inset = n * 2 + 1;
for(int i = 1; i <= n; ++i){
add(outset, i, 1, 0);
add(i + n, inset, 1, 0);
}
while(m--){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b + n, 1, c);
}
}
bool SPFA(int st, int ed){
queue<int>q;
for(int i = 0; i <= inset; ++i){
dist[i] = INF;
vis[i] = 0;
per[i] = -1;
}
dist[st] = 0;
vis[st] = 1;
q.push(st);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u]; i != -1; i = edge[i].next){
node E = edge[i];
if(dist[E.v] > dist[u] + E.cost && E.cap > E.flow){//可以松弛 且 没有满流
dist[E.v] = dist[u] + E.cost;
per[E.v] = i;//记录到达这个点的边的编号
if(!vis[E.v]){
vis[E.v] = 1;
q.push(E.v);
}
}
}
}
return per[ed] != -1;
}
void MCMF(int st, int ed, int &cost, int &flow){
flow = 0;//总流量
cost = 0;//总费用
while(SPFA(st, ed)){//每次寻找花销最小的路径
int mins = INF;
for(int i = per[ed]; i != -1; i = per[edge[i ^ 1].v]){
mins = min(mins, edge[i].cap - edge[i].flow);
}
//增广
for(int i = per[ed]; i != -1; i = per[edge[i ^ 1].v]){
edge[i].flow += mins;
edge[i ^ 1].flow -= mins;
cost += edge[i].cost * mins;
}
flow += mins;
}
}
int main (){
while(scanf("%d%d", &n, &m) != EOF){
init();
getmap();
int cost, flow;
MCMF(outset, inset, cost, flow);
if(flow == n)
printf("%d\n", cost);
else
printf("-1\n");
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 1853--Cyclic Tour【最小费用最大流 && 有向环最小权值覆盖 】
原文地址:http://blog.csdn.net/hpuhjh/article/details/48039633