#105-[费用流]最小费用流

版权声明:反正也没有人会转,下一个 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;
}

猜你喜欢

转载自blog.csdn.net/drtlstf/article/details/82811592