1. 程式人生 > >TOJ 1583: Farm Tour -- 最小費用最大流 MCMF

TOJ 1583: Farm Tour -- 最小費用最大流 MCMF

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mp make_pair
using namespace std;

typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
typedef pair pii;
typedef vector vi;
typedef vi::iterator vi_it;
typedef map mii;
typedef priority_queue pqi;
typedef priority_queue, greater > rpqi;

const int MAX_NODE = 1000 + 10;
const int MAX_EDGE = 10000 + 10;
const int INF = (int)1.0e9;
int p[MAX_NODE];	//predecessor array
int d[MAX_NODE];	//cost array(from the source)
bool inq[MAX_NODE];	//in-queue flag
int cnt = 0;	//edge counting
int head[MAX_NODE];

struct
{
	int u;
	int v;
	int cap;
	int cost;
	int next;
} edge[MAX_EDGE << 2];

void add_edge(int u, int v, int cap, int cost)
{
	edge[cnt].u = u;
	edge[cnt].v = v;
	edge[cnt].cap = cap;
	edge[cnt].cost = cost;
	edge[cnt].next = head[u];
	head[u] = cnt++;
	edge[cnt].u = v;
	edge[cnt].v = u;
	edge[cnt].cap = 0;
	edge[cnt].cost = -cost;
	edge[cnt].next = head[v];
	head[v] = cnt++;
}

class MCMF
{
	public:
	/**
		Description:
	
		Arguments:
	 	n -- the number of nodes
	 	s -- the source
	 	t -- the destination
	
		Returns:pair
	
	*/
	pii mcmf(int n, int s, int t);
};

pii MCMF::mcmf(int n, int s, int t)
{
	queue q;
	int c = 0;	//min cost
	int f = 0;	//max flow
	int u, v, i;
	
	while (true) {
		memset(inq, 0, sizeof(inq));
		for (i = 0; i < n; ++i) {
			d[i] = INF;
		}
		d[s] = 0;
		q.push(s);
		inq[s] = true;
		p[s] = -1;
		while (!q.empty()) {
			u = q.front();
			q.pop();
			inq[u] = false;
			for (i = head[u]; i != -1; i = edge[i].next) {
				v = edge[i].v;
				if (edge[i].cap > 0 && d[v] > d[u] + edge[i].cost) {
					d[v] = d[u] + edge[i].cost;
					p[v] = i;
					if (!inq[v]) {
						q.push(v);
						inq[v] = true;
					}
				}
			}
		}
		
		if (d[t] == INF) {
			return mp(f, c);
		}
		
		int a = INF;
		for (i = p[t]; i != -1; i = p[edge[i].u]) {
			a = min(a, edge[i].cap);
		}
		for (i = p[t]; i != -1; i = p[edge[i].u]) {
			edge[i].cap -= a;
			edge[i ^ 1].cap += a;
		}
		
		c += d[t] * a;
		f += a;
	}
	
	return mp(-1, -1);	//an error occurs
}

int main(int argc, char *argv[])
{
//	freopen("D:\\in.txt", "r", stdin);
	int n, m;
	cin >> n >> m;
	memset(head, -1, sizeof(head));	
	while (m--) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		add_edge(u, v, 1, w);
		add_edge(v, u, 1, w);
	}
	
	add_edge(0, 1, 2, 0);
	add_edge(n, n + 1, 2, 0);
	MCMF mc;
	pii ans = mc.mcmf(n + 2, 0, n + 1);
	assert(ans.first == 2);
	cout << ans.second << endl;
	return 0;
}