【USACO4.2.1】草地排水 最大流

13 篇文章 0 订阅
5 篇文章 0 订阅

直接套用ISAP模板


我的模板不一定正确…… 不能参考!!!!!



/*
TASK:ditch
LANG:C++
*/

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

const int max_ver = 200 + 10;
int n, m;
struct edge
{
	int ver, cap, flow;
	edge *next, *rev;
	edge(){}
	edge(int _Ver, int _Cap, edge* _Next):ver(_Ver), cap(_Cap), next(_Next), flow(0), rev(NULL){}
}*net[max_ver]={NULL};

inline void insert_edge(int s, int t, int cap)
{
	net[s] = new edge(t, cap, net[s]);
	net[t] = new edge(s, 0, net[t]);
	net[s] -> rev = net[t];
	net[t] -> rev = net[s];
}

void init()
{
	scanf("%d%d", &m, &n);
	while (m--)
	{
		int a, b , c;	
		scanf("%d%d%d", &a, &b, &c);
		insert_edge(a, b, c);
	}
}

queue<int>q;
int dist[max_ver], numbs[max_ver];


void rev_bfs(int s = 1, int t = n)
{
	q.push(t);
	for (int i = 1; i <= n; ++ i)	dist[i] = 0x7fffffff;
	memset(numbs, 0, sizeof(numbs));
	numbs[0] = 1;
	q.push(t);
	dist[t] = 0;
	while (!q.empty())
	{
		int now = q.front();
		q.pop();
		for (edge *e = net[now]; e; e = e -> next)
		{
			int will = e -> ver;	
			if (dist[will] != 0x7fffffff || e -> rev -> cap == 0)	continue;
			dist[will] = dist[now] + 1;
			++ numbs[dist[will]];
			q.push(will);
		}
	}
}

edge *CurEdge[max_ver], *revpath[max_ver];
int totflow(0);

void augflow(int s = 1, int t = n)
{
	int augflow = 0x7fffffff;
	for (int i = s; i != t; i = CurEdge[i] -> ver)
	{
		//cout<<"["<<i<<"]"<<endl;
		augflow = min(augflow, CurEdge[i] -> cap);
	}
	for (int i = s; i != t; i = CurEdge[i] -> ver)
	{
		CurEdge[i] -> cap -= augflow;	
		CurEdge[i] -> rev -> cap += augflow;
		CurEdge[i] -> flow += augflow;
		CurEdge[i] -> rev -> flow -= augflow;
	}
	totflow += augflow;
}

void maxflow(int s = 1, int t = n)
{
	int totalflow = 0;
	for (int i = 1; i <= n; ++ i)	CurEdge[i] = net[i];//当前弧优化!
	int now = s;
	while (dist[s] < n) // 起点到终点的距离比n小。一旦到n,肯定是到不了。 比如1->2 如果1->2距离是2,肯定是不可能的
	{
		if (now == t)
		{
			augflow();	
			now = s;
		}
		edge *e;
		for (e = CurEdge[now]; e; e = e -> next)
			if (e -> cap > 0 && dist[now] == dist[e -> ver] + 1)	break;//找到一个可行的路
		if (e)
		{
			CurEdge[now] = e;	
			revpath[e -> ver] = e -> rev; //计算will是从哪里来的,为了回溯
			now = e -> ver;
		}else{ //失败了,显然要回溯
			if (0 == (--numbs[dist[now]]))	break; //如果一个距离已经没有了。 出现断层了 显然就应该结束了
			CurEdge[now] = net[now];
			int mindist = n;
			for (edge *te = net[now]; te; te = te -> next)
				if (te -> cap >0)	mindist = min(mindist, dist[te -> ver]);
			dist[now] = mindist + 1;
			++ numbs[dist[now]];
			if (now != s)	now = revpath[now] -> ver;
		}
	}
	printf("%d\n", totflow);
}

int main()
{
	freopen("ditch.in","r",stdin);
	freopen("ditch.out","w",stdout);
	init();
	rev_bfs(1, n);
	maxflow(1, n);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值