最小费用最大流:保证最大流的同时使得费用最小
这道题要求从1-n和n-1总的最短路径,模拟每条路流量为1,费用为路径长度,用spfa进行处理,并设置源点和汇点(费用0,流量2),模拟最小费用最大流
E'K'算法(把EK的bfs寻路换成spfa即可)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1005;
const int maxm = 40005;
bool vis[maxn];
int pre[maxn], d[maxn], head[maxn];
int cnt;
int n, m;
int u, v, w, c;
int s, t;
struct node
{
int s, to, next, w, c;
}e[maxm];
void init()
{
memset(head, - 1, sizeof(head));
s = n + 1, t = n + 2;
cnt = 0;
}
void addedge(int u, int v, int w, int c)//w是路径花费,c是流量
{
e[cnt].s = u;
e[cnt].to = v;
e[cnt].w = w;
e[cnt].c = c;
e[cnt].next = head[u];
head[u] = cnt ++;
e[cnt].s = v;
e[cnt].to = u;
e[cnt].w = -w;
e[cnt].c = 0;
e[cnt].next = head[v];
head[v] = cnt ++;
}
bool spfa()
{
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
memset(d, 0x3f, sizeof(d));
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = 1;
while(! q.empty())
{
int h = q.front();
q.pop();
vis[h] = 0;
for(int i = head[h]; ~i; i = e[i].next)
{
if(e[i].c)
{
int v = e[i].to;
if(d[h] + e[i].w < d[v])
{
d[v] = d[h] + e[i].w;
pre[v] = i;
if(! vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
}
if(d[t] == inf) return 0;
else return 1;
}
int EK()
{
int cost = 0;
int tt, minc;
while(spfa())
{
tt = t;
minc = inf;
while(pre[tt] != -1)
{
minc = min(e[pre[tt]].c, minc);
tt = e[pre[tt]].s;
}
tt = t;
while(pre[tt] != -1)
{
e[pre[tt]].c -= minc;
e[pre[tt]^1].c += minc;
tt = e[pre[tt]].s;
}
cost += d[t] * minc;
}
return cost;
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF)
{
init();
for(int i = 1; i <= m; i ++)
{
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w, 1);
addedge(v, u, w, 1);
}
addedge(s, 1, 0, 2);
addedge(n, t, 0, 2);
printf("%d\n", EK());
}
return 0;
}