最小费用最大流(模板题)

poj2125
题目大意:
给你一个无向图,有n个点,m条边,求从1 ~ n,然后再从n ~ 1 ,且每一条边只能走一次,求最短路径是多少。

思路:
因为每一条边只能走一次,所以可以将每一条边的流量设置为1,要么用流过该条边,要么都不流。将每一条边的权值置为该条边的费用,然后跑两遍spfa最短路求最小费用就好了。

模板:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+10;
const int M=4e4+10;
int n,m,ss,tt;
int dis[N],head[M<<1],tot=1,vis[N],incf[N],pre[N];
struct edge {
    
    
    int to,next,w,flow;
}E[M<<1];
void add(int from,int to,int flow,int w) {
    
    
    E[++tot].to=to;
    E[tot].flow=flow;
    E[tot].w=w;
    E[tot].next=head[from];
    head[from]=tot;
}
bool spfa(int s,int t) {
    
    
    queue<int>q;
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    q.push(s);
    dis[s]=0,vis[s]=1;
    incf[s]=INF; //初始流量无限大
    while(!q.empty()) {
    
    
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];~i;i=E[i].next) {
    
    
            if(!E[i].flow) continue;
            int to=E[i].to;
            
            if(dis[to]>dis[u]+E[i].w) {
    
    
                dis[to]=dis[u]+E[i].w;
                incf[to]=min(incf[u],E[i].flow);
                pre[to]=i;
                if(!vis[to]) {
    
    
                    vis[to]=1;
                    q.push(to);
                }
            }
        }
    }
    if(dis[t]==INF) return false;
    return true;
}
void dinic(int s,int t) {
    
    
    int maxflow=0;
    int mincost=0;
    while(spfa(s,t)) {
    
    
        int x=t;
        maxflow+=incf[t];
        mincost+=dis[t]*incf[t];
        while(x!=s) {
    
    
            int i=pre[x];
            E[i].flow-=incf[t];
            E[i^1].flow+=incf[t];
            x=E[i^1].to;
        }
        if(maxflow==2) break;  //最大流为2说明已经找到两到从1-n的最短路了
    }
    //if(maxflow<2) cout << "-1" << endl;   因为题目所给的数据一定存在两条最短路,所以这一句没啥用,,,,,
    cout << mincost << endl;
    
}
void init() {
    
    
    tot=1;
    memset(head,-1,sizeof(head));
}
int main() {
    
    
    ios::sync_with_stdio(false);
    init();
    cin >> n >> m;
    for(int i=0;i<m;i++) {
    
    
        int u,v,w,x;
        cin >> u >> v >> w;
        //因为是无向图,所以相当于要加入4条边
        add(u,v,1,w);
        add(v,u,0,-w);
        add(v,u,1,w);
        add(u,v,0,-w);
    }

    dinic(1,n);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45937795/article/details/119427613
今日推荐