最小费用最大流

poj2135

模板

题意:有n个点,m条边,FJ要从1走到n,再从n走回1,走的边不能重复,找这样一个来回的最短路径。

转为最小费用最大流来做,也就是说每条边只能用一次,我们把给出的每条边的长度作为这条边的花费,然后设边的容量为1

因为是无向图,所以对于每条边(x,y)要建立四条边,x->y容量为1费用为L(长度)的边,y->x容量为0费用为(-L)的边,

y->x容量为1,费用为L的边,x->y容量为0,费用为-L的边。

再建立一个超级源点和超级汇点。

超级源点(0)->1的容量为2(可以正反走两次),费用为0

n-超级汇点(n+1)的容量为2,费用为0

依次建立四条边。

套上费用流的板子即可得到答案。

#include
#include
#include
#include
#define memset(a,v) memset(a,v,sizeof(a))
using namespace std;
const int MAXN(1e3);
const int MAXM(1e4);
const int INF(0x3f3f3f3f);
struct node {
    int to,next,cap,cost;
    node(){}
    node(int to,int next,int cap,int cost):to(to),next(next),cap(cap),cost(cost){}
}edge[4*MAXM+50];
int head[4*MAXM+50];
bool vis[MAXN+50];
int dis[MAXN+50];
int pre[MAXN+50];
int path[MAXN+50];
int n,m,cnt;
void init() {
    cnt=0;
    memset(head,-1);
}
void add_edge(int u,int v,int cap,int cost) {
    edge[cnt]=node(v,head[u],cap,cost);
    head[u]=cnt++;
    edge[cnt]=node(u,head[v],0,-cost);
    head[v]=cnt++;
}
bool SPFA(int s,int t) {
    memset(dis,INF); memset(pre,-1); memset(vis,false);
    queueq;
    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 ;i=edge[i].next) {
            int to=edge[i].to,cost=edge[i].cost;
            if(edge[i].cap>0&&dis[u]+cost

 

你可能感兴趣的:(一些算法模板,图论)