您的位置:首页 > 其它

POJ 2135 Farm Tour【最小费用流】

2015-07-20 13:32 204 查看
意:N个点,M条边,从1号点出发到N号点,再走回来,且不能走走过的路,求最小路径权和

最小费用流,用流量为1 限制每条边只能走一次,建立超源汇点,源点连1号点的流量为2,费用0,汇点同理。其他边的流量为1,费用为权值。

建立超源汇点且权值为2目的是因为起终点经过2次(虽然这里是点经过2次而题目是边),而如果不建超源点的话没办法表示,如果是直接把跟1号点相连的都设置为2,则很多边都可以走2次了,不科学了。
建立a->b的边时建反向弧,也建立b->a的边,这样当一去一回的情况下流量就为0了
下面模板是kuangbin的,模板大法好

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define eps 10^(-6)
#define Q_CIN ios::sync_with_stdio(false)
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) )
#define RE freopen("1.in","r",stdin);
#define WE freopen("1.out","w",stdout);
#define MOD 10009
#define NMAX 10002
//模板大法好
const int inf = 0x3f3f3f3f;
const int maxn = 1005;
const int maxm = 10000 * 2 + 10;
struct Edge {
int to, next, cap, flow, cost;
} edge[maxm * 2];
int head[maxn], tol;
int pre[maxn], dis[maxn];
bool vis[maxn];
void init() {
tol = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int cap, int cost) {
edge[tol].to = v;
edge[tol].cap = cap;
edge[tol].cost = cost;
edge[tol].flow = 0;
edge[tol].next = head[u];
head[u] = tol++;
edge[tol].to = u;
edge[tol].cap = 0;
edge[tol].cost = -cost;
edge[tol].flow = 0;
edge[tol].next = head[v];
head[v] = tol++;
}
bool spfa(int s, int t) {
queue<int>q;
memset(dis, inf, sizeof(dis));
memset(vis, false, sizeof(vis));
memset(pre, -1, sizeof(pre));
dis[s] = 0;
vis[s] = true;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if (edge[i].cap > edge[i].flow &&
dis[v] > dis[u] + edge[i].cost ) {
dis[v] = dis[u] + edge[i].cost;
pre[v] = i;
if (!vis[v]) {
vis[v] = true;
q.push(v);
}
}
}
}
return pre[t] != -1;
}
//返回最大流,cost存最小费用
int minCostMaxflow(int s, int t, int &cost) {
int flow = 0;
cost = 0;
while (spfa(s, t)) {
int Min = inf;
for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
if (Min > edge[i].cap - edge[i].flow) {
Min = edge[i].cap - edge[i].flow;
}
}
for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
edge[i].flow += Min;
edge[i ^ 1].flow -= Min;
cost += edge[i].cost * Min;
}
flow += Min;
}
return flow;
}
int main() {
int n, m, a, b, c;
//        freopen("1.in","r",stdin);
while (~scanf("%d%d",&n,&m)) {
int ss = 0, tt = n + 1;
init();
addEdge(ss, 1, 2, 0);
addEdge(n, tt, 2, 0);
while (m--) {
scanf("%d%d%d",&a,&b,&c);
addEdge(a, b, 1, c);
addEdge(b, a, 1, c);
}
int cost;
minCostMaxflow(ss, tt, cost);
printf("%d\n",cost);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: