poj3281Dining网络流-最大流

本文详细阐述了一种流量拆点优化算法的应用实例,通过将牛拆分为饮料、牛、食物三个部分,确保流量能够同时经过这三个环节,从而保证了解决方案的正确性和效率。算法采用Dinic算法实现,同时提供了代码实现细节和优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

就向之前那篇博客写得一样,这里就是需要拆点的.把每头牛拆成:

饮料->牛->牛->食物.

想像一下,这样的话,如果有流量经过这条路线,就一定可以让这段流量同时经过牛-食物-饮料三件套.就可以保证解的正确性了~~~

Memory: 1580K Time: 47MS


用dinic写的.如果用其它算法(EK,sap,isap,FF都以),只是建图这里保证搞清楚 就好了.当然我们只是保证解的正确性,那你要问,我搞成食物->牛->牛->饮料可以不?当然是可以的!

好了,就这样了.

对了如果还不清楚,看我2小时前写得那篇总结.里面有关于拆点的说明,还有这种问题要加的"炒鸡源点"和"炒鸡汇点"这两个特殊点.

#include <cstdio>
#include <cstring>
#include <climits>
#include <algorithm>
#include <queue>
using namespace std;
const int MAX_V = 512;
const int INF = INT_MAX>>1;
int G[MAX_V][MAX_V];
int level[MAX_V];
int n, f, d, all;

bool bfs(int s, int t) {
	memset(level, -1, sizeof(level));
	queue<int> Q; int p;
	level[s] = 0;
	Q.push(s);
	while (!Q.empty()) {
		p = Q.front(); Q.pop();
		for (int i = 0; i < all; ++i) {
			if (G[p][i] > 0 && level[i] < 0) {
				level[i] = level[p] + 1;
				Q.push(i);
				if (i == t) return true;
			}
		}
	}
	return false;
}

int dfs(int s, int t, int flow) {
	if (s == t) return flow;
	int res = 0, tmp;
	for (int i = 0; i < all; ++i) {
		if (G[s][i] > 0 && level[i] == level[s] + 1) {
			tmp = dfs(i, t, min(flow, G[s][i]));
			G[s][i] -= tmp;
			G[i][s] += tmp;
			res += tmp; flow -= tmp;
		}
	}
	return res;
}

int dinic(int s, int t) {
	int flow = 0;
	while (bfs(s, t)) flow += dfs(s, t, INF);
	return flow;
}

int main() {
	while (~scanf(" %d %d %d", &n, &f, &d)) {
		memset(G, 0, sizeof(G));
		/* 0炒鸡源点,1~f食物,f+1~f+n牛B,f+n+1~f+2*n牛屌,(牛要拆点
		 * f+2*n+1~f+2*n+d饮料,f+2*n+d+1炒鸡汇点
		 */
		all = f+(n<<1)+d+2;

		for (int i = 1; i <= f; ++i) G[0][i] = 1;
		for (int i = f+(n<<1)+1; i < all; ++i) G[i][all-1] = 1;

		int cf, cd, val; //cow's food, cow's drink, value of anyone of them
		for (int i = 1; i <= n; ++i) {
			scanf(" %d %d", &cf, &cd);
			for (int j = 1; j <= cf; ++j) {
				scanf(" %d", &val);
				G[val][i+f] = 1;
			}//食物和牛逼连起来
			G[i+f][i+f+n] = 1; //牛逼和牛屌连以来
			for (int j = 1; j <= cd; ++j) {
				scanf(" %d", &val);
				G[i+f+n][f+(n<<1)+val] = 1;
			}//牛屌和饮料连起来
		}

		printf("%d\n", dinic(0, all-1));
	}
	return 0;
}

呃,至于邻接矩阵被吐槽,是因为我智力有限,觉得这玩意方便....链表之后补学一下..........
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值