版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/82811592
Description
这是一道模板题。
给定一个图,每条边有容量和费用,使用每条边的单位流量需要支付特定的费用。给定源点 1 和汇点 n,求图的最大流和最大流需要支付的最小费用。
Input
第一行两个整数 n 、m ,表示有 n 个点 m 条边。
从第二行开始的之后 m 行,每行四个整数 si 、ti、ci 、wi 表示一条从 si 到 ti 的边,容量为 ci ,单位流量需要支付的费用为 wi 。
Output
一行两个整数,分别表示最大流和最大流需要支付的最小费用。
Sample Input
8 23
2 3 2147483647 1
1 3 1 1
2 4 2147483647 2
1 4 1 2
2 8 2 0
3 5 2147483647 3
1 5 1 3
3 6 2147483647 4
1 6 1 4
3 8 2 0
3 2 2147483647 0
4 6 2147483647 5
1 6 1 5
4 7 2147483647 6
1 7 1 6
4 8 2 0
4 2 2147483647 0
5 8 0 0
5 2 2147483647 0
6 8 0 0
6 2 2147483647 0
7 8 0 0
7 2 2147483647 0
Sample Output
6 24
HINT
【数据范围与提示】
1≤n≤400,0≤m≤15000,wi≥0,保证输入数据、中间结果以及答案在 32 位有符号整数范围内。
亏我背了一个月的费用流模板
#include <iostream>
#include <cstring>
#include <queue>
#define SIZE 450
#define INF 2147483647
using namespace std;
struct edge
{
int to, cap, cost, reverse;
};
vector<edge> graph[SIZE];
queue<int> q;
int dis[SIZE], pre[SIZE], edgeindex[SIZE], maxflow, mincost, n;
bool inqueue[SIZE];
void addedge(int from, int to, int cap, int cost) // 建边(反向建边似神仙)
{
graph[from].push_back({to, cap, cost, graph[to].size()});
graph[to].push_back({from, 0, -cost, graph[from].size() - 1});
return;
}
bool bfs(void) // 其实是SPFA
{
queue<int> q;
int u, v, w, i;
memset(pre, -1, sizeof (pre));
memset(dis, 63, sizeof (dis));
memset(edgeindex, -1, sizeof (edgeindex));
q.push(1);
dis[1] = 0;
while (!q.empty())
{
u = q.front();
q.pop();
inqueue[u] = false;
for (i = 0; i < graph[u].size(); ++i)
{
if (graph[u][i].cap)
{
v = graph[u][i].to;
w = graph[u][i].cost;
if (dis[u] + w < dis[v])
{
dis[v] = dis[u] + w;
pre[v] = u;
edgeindex[v] = i;
if (!inqueue[v])
{
q.push(v);
inqueue[v] = true;
}
}
}
}
}
return ~pre[n];
}
void getmincostmaxflow(void)
{
int delta, u, v, id;
while (bfs())
{
u = n;
v = pre[n];
delta = INF;
while (~v)
{
delta = min(delta, graph[v][edgeindex[u]].cap);
u = v;
v = pre[v];
}
u = n;
v = pre[n];
maxflow += delta;
while (~v)
{
id = edgeindex[u]; // 扩容
graph[v][id].cap -= delta;
graph[u][graph[v][id].reverse].cap += delta;
mincost += delta * graph[v][id].cost;
u = v;
v = pre[v];
}
}
return;
}
int main(void)
{
int m, u, v, w, c;
scanf("%d%d", &n, &m);
while (m--)
{
scanf("%d%d%d%d", &u, &v, &w, &c); // 建图
addedge(u, v, w, c);
}
getmincostmaxflow();
printf("%d %d", maxflow, mincost);
return 0;
}