Farm Tour POJ - 2135 費用流

題解

要求從起點到終點在回到起點,可以看做起點到終點流量爲2的網絡流。題目所給出的邊沒有方向設置爲兩條容量爲1的有向邊。
限制流大小爲2,最後跑最小費用最大流即可。

AC代碼

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <string.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e3 + 10;
const int M = 1e4 + 10;
int n, m, st, ed;
bool vis[N]; //在隊列的節點
int dis[N], pre[N]; //pre最短路前驅通往當前點的邊

struct edge
{
	int v, w, c, nxt; //w容量 c代價
	edge() {}
	edge(int vv, int ww, int cc, int nx) : v(vv), w(ww), c(cc), nxt(nx) {}
}e[M * 4];
int h[N], idx;
void AddEdge(int u, int v, int w, int c)
{
	e[idx] = edge(v, w, c, h[u]);
	h[u] = idx++; //後++編號0到idx-1 結束爲-1
}
bool SPFA(int st, int ed) //每個點相對於st的層次 也就是邊權爲1的最短路
{
	queue<int> q;
	memset(dis, 0x3f, sizeof(dis));
	memset(pre, -1, sizeof(pre));
	dis[st] = 0;
	vis[st] = 1;
	q.push(st);
	while (!q.empty())
	{
		int u = q.front(); q.pop(), vis[u] = 0;
		for (int i = h[u]; ~i; i = e[i].nxt)
		{
			int v = e[i].v, w = e[i].w, c = e[i].c; //w流量 c代價
			if (dis[v] > dis[u] + c && w) //代價更低且未滿流
			{
				dis[v] = dis[u] + c; //更新代價
				pre[v] = i; //記錄邊編號
				if (!vis[v]) //不在隊伍內則入隊
					q.push(v), vis[v] = 1;
			}
		}
	}
	return pre[ed] != -1; //返回st是否和ed連通
}
void MCMF(int st, int ed, int &cost)
{
	cost = 0;
	int free = 2; //剩餘所需流量 迴路流量爲2即可
	while (free && SPFA(st, ed))
	{
		int mi = free;
		for (int i = pre[ed]; ~i; i = pre[e[i ^ 1].v])
			mi = min(mi, e[i].w);
		for (int i = pre[ed]; ~i; i = pre[e[i ^ 1].v])
		{
			e[i].w -= mi, e[i ^ 1].w += mi;
			cost += mi * e[i].c; //流量*當前邊代價
		}
		free -= mi;
	}
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	memset(h, -1, sizeof(h));
	cin >> n >> m;
	for (int i = 0; i < m; ++i)
	{
		int u, v, c;
		scanf("%d%d%d", &u, &v, &c);
		AddEdge(u, v, 1, c);
		AddEdge(v, u, 0, -c); //反向邊和正向連續建立!!
		AddEdge(v, u, 1, c); //無向圖雙向邊 反向0容量負權
		AddEdge(u, v, 0, -c);
	}
	int cost = 0;
	MCMF(1, n, cost); //1到n再回來
	printf("%d\n", cost);

	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章