ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

网络最大流三题

2022-08-20 00:01:40  阅读:137  来源: 互联网

标签:最大 gdx int eg 网络 dep add rep 流三题


昨天杭电多校1001题人均过,该学学网络流了(虽然dls说过,网络流只能出金牌题)

在b站看了电子科大的网络流入门,学会了dinic的板子,还不会严格证明

求单源单汇的最大流,简单来说就是只要残量网络能够到达汇点,就跑一遍增广路,然后再求残量网络,再跑增广路……直到汇点无法到达。
关键点:建反向边,残量网络通过分层图来判断,dinic优化
其中,dinic优化又分为当前弧优化、多路增广和炸点
当前弧优化貌似useless,多路增广就是将当前点能够走通的路全走一遍再返回,炸点就是把没用的点堵塞

最大流三题:

洛谷P3376 【模板】网络最大流
最大流的模板题

#include<bits/stdc++.h>
using namespace std;

#define fr first
#define se second
#define et0 exit(0);
#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
#define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --)
#define IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef unsigned long long ULL;

const int INF = 0X3f3f3f3f, N = 200 + 10, M = 5000 + 10, MOD = 1e9 + 7;
const double eps = 1e-7, pi = acos(-1);

int aim;

int dep[N];

int head[N], idx;

struct EGDE {
	int to, next; 
	LL w;
} eg[M << 1];

void add(int x, int y, int w) {
	eg[idx].to = y;
	eg[idx].next = head[x];
	eg[idx].w = w;
	head[x] = idx++;
}

int bfs(int S, int T) {
	queue<int> Q;
	memset(dep, 0, sizeof dep);
	dep[S] = 1;
	Q.push(S);
	
	while (!Q.empty()) {
		int u = Q.front();
		Q.pop();
		for (int i = head[u]; ~i; i = eg[i].next) {
			int to = eg[i].to;
			if (eg[i].w && !dep[to]) {
				dep[to] = dep[u] + 1;
				Q.push(to);
			}
		}
	}
	
	return dep[T];
}

LL dfs(int u, LL rf) {
	if (u == aim) return rf;
	
	LL uf = 0;
	for (int i = head[u]; ~i; i = eg[i].next) {
		int to = eg[i].to;
		if (eg[i].w && dep[to] == dep[u] + 1) {
			LL tf = dfs(to, min(rf, eg[i].w));
			eg[i].w -= tf, eg[i ^ 1].w += tf;
			rf -= tf, uf += tf;
		}
	}
	
	if (!uf) dep[u] = -2;
	return uf;
}

LL maxflow(int S, int T) {
	LL res = 0;
	aim = T;
	
	while (bfs(S, T)) res += dfs(S, 1ll << 31);
	
	return res;
}

void work() {
	int n, m, s, t;
	memset(head, -1, sizeof head);

	cin >> n >> m >> s >> t;
	rep (i, 1, m) {
		LL u, v, w;
		cin >> u >> v >> w;
		add(u, v, w), add(v, u, 0);
	}
	
	cout << maxflow(s, t) << endl;
}

signed main() {
	IO

	int test = 1;
//	cin >> test;

	while (test--) {
		work();
	}

	return 0;
}

洛谷P1264 K-联赛

这题难就难在建图。
第\(i\)个队伍想要获胜,首先自己的胜场要尽可能多,也就是接下来跟自己有关的比赛全部获胜,设胜场为\(w_i\);
那么剩下的每个队伍胜场都不能超过\(w_i\),从每个队伍\(j\)向\(i\)连一条容量为\(w_i-w_j\)的边;
然后将队伍之间的比赛也当做若干个节点,从源点向比赛连一个边权为比赛数的边,再从比赛向两个队伍分别连边权为比赛数的边;
在边权的容量限制下,可以证明只要最大流为剩余比赛数,就一定有一种合法的比赛方案使第\(i\)队获胜。

#include<bits/stdc++.h>
using namespace std;

#define fr first
#define se second
#define et0 exit(0);
#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
#define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --)
#define IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef unsigned long long ULL;

const int INF = 0X3f3f3f3f, N = 1000 + 10, M = 2000 + 10, MOD = 1e9 + 7;
const double eps = 1e-7, pi = acos(-1);

int n;
int w[N], g[N][N];

int aim;
int dep[N];

int head[N], idx, gdx;

struct EGDE {
	int to, next, w;
} eg[M << 1];

void add(int x, int y, int w) {
	eg[idx].to = y;
	eg[idx].next = head[x];
	eg[idx].w = w;
	head[x] = idx++;
}

int bfs(int S, int T) {
	queue<int> Q;
	memset(dep, 0, sizeof dep);
	dep[S] = 1;
	Q.push(S);
	
	while (!Q.empty()) {
		int u = Q.front();
		Q.pop();
		for (int i = head[u]; ~i; i = eg[i].next) {
			int to = eg[i].to;
			if (eg[i].w && !dep[to]) {
				dep[to] = dep[u] + 1;
				Q.push(to);
			}
		}
	}
	
	return dep[T];
}

int dfs(int u, int rf) {
	if (u == aim) return rf;
	
	int uf = 0;
	for (int i = head[u]; ~i; i = eg[i].next) {
		int to = eg[i].to;
		if (eg[i].w && dep[to] == dep[u] + 1) {
			int tf = dfs(to, min(rf, eg[i].w));
			eg[i].w -= tf, eg[i ^ 1].w += tf;
			rf -= tf, uf += tf;
		}
	}
	
	if (!uf) dep[u] = -2;
	return uf;
}

int maxflow(int S, int T) {
	int res = 0;
	aim = T;
	
	while (bfs(S, T)) res += dfs(S, 1 << 20);
	
	return res;
}

void work() {
	int tmp;
	cin >> n;
	rep (i, 1, n) cin >> w[i] >> tmp;
	rep (i, 1, n) rep (j, 1, n) cin >> g[i][j];
	
	rep (i, 1, n) {
		int sum = 0;
		bool ok = true;
		idx = 0, gdx = n;
		memset(head, -1, sizeof head);
		
		int wi = w[i];
		rep (j, 1, n) wi += g[i][j];
		rep (j, 1, n) {
			if (j == i) continue;
			if (wi < w[j]) {
				ok = false;
				break;
			}
			add(j, i, wi - w[j]), add(i, j, 0);
		}
		rep (j, 1, n) {
			if (j == i) continue;
			rep (k, j + 1, n) {
				if (k == i) continue;
				sum += g[j][k];
				gdx++;
				add(0, gdx, g[j][k]), add(gdx, 0, 0);
				add(gdx, j, g[j][k]), add(j, gdx, 0);
				add(gdx, k, g[j][k]), add(k, gdx, 0);
			}
		}
		if (!ok) continue;
		
		int t = maxflow(0, i); 
		if (t == sum) cout << i << " ";
	}
	cout << endl;
}

signed main() {
	IO
	
	int test = 1;
//	cin >> test;

	while (test--) {
		work();
	}

	return 0;
}

杭电多校第十场 1001 Winner Prediction

跟上题类似,建图方式是一样的

#include<bits/stdc++.h>
using namespace std;

#define fr first
#define se second
#define et0 exit(0);
#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
#define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --)
#define IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef unsigned long long ULL;

const int INF = 0X3f3f3f3f, N = 2000 + 10, M = 5000 + 10, MOD = 1e9 + 7;
const double eps = 1e-7, pi = acos(-1);

int n;
int w[N];

int aim;
int dep[N];

int head[N], idx, gdx;

struct EGDE {
	int to, next, w;
} eg[M << 1];

void add(int x, int y, int w) {
	eg[idx].to = y;
	eg[idx].next = head[x];
	eg[idx].w = w;
	head[x] = idx++;
}

int bfs(int S, int T) {
	queue<int> Q;
	memset(dep, 0, sizeof dep);
	dep[S] = 1;
	Q.push(S);
	
	while (!Q.empty()) {
		int u = Q.front();
		Q.pop();
		for (int i = head[u]; ~i; i = eg[i].next) {
			int to = eg[i].to;
			if (eg[i].w && !dep[to]) {
				dep[to] = dep[u] + 1;
				Q.push(to);
			}
		}
	}
	
	return dep[T];
}

int dfs(int u, int rf) {
	if (u == aim) return rf;
	
	int uf = 0;
	for (int i = head[u]; ~i; i = eg[i].next) {
		int to = eg[i].to;
		if (eg[i].w && dep[to] == dep[u] + 1) {
			int tf = dfs(to, min(rf, eg[i].w));
			eg[i].w -= tf, eg[i ^ 1].w += tf;
			rf -= tf, uf += tf;
		}
	}
	
	if (!uf) dep[u] = -2;
	return uf;
}

int maxflow(int S, int T) {
	int res = 0;
	aim = T;
	
	while (bfs(S, T)) res += dfs(S, 1 << 27);
	
	return res;
}

void work() {
	int sum = 0, m1, m2;
	bool ok = true;
	idx = 0;
	memset(head, -1, sizeof head);

	cin >> n >> m1 >> m2;
	gdx = n;
	
	rep (i, 1, n) w[i] = 0;
	rep (i, 1, m1) {
		int x, y, z;
		cin >> x >> y >> z;
		if (z) w[x]++;
		else w[y]++;
	} 
	rep (i, 1, m2) {
		int x, y;
		cin >> x >> y;
		if (x == 1 || y == 1) w[1]++;
		else {
			sum++;
			gdx++;
			add(0, gdx, 1), add(gdx, 0, 0);
			add(gdx, x, 1), add(x, gdx, 0);
			add(gdx, y, 1), add(y, gdx, 0);	
		}
	}
	
	int w1 = w[1];
	rep (i, 2, n) {
		if (w1 < w[i]) {
			ok = false;
			break;
		}
		add(i, 1, w1 - w[i]), add(1, i, 0);
	}
	if (!ok) {
		cout << "NO" << endl;
		return;
	}
	
	int t = maxflow(0, 1); 
	if (t == sum) cout << "YES" << endl;
	else cout << "NO" << endl;
	
	rep (i, 0, n) w[i] = 0;
}

signed main() {
	IO
	memset(head, -1, sizeof head);
	
	int test = 1;
	cin >> test;

	while (test--) {
		work();
	}

	return 0;
}

标签:最大,gdx,int,eg,网络,dep,add,rep,流三题
来源: https://www.cnblogs.com/xhy666/p/16606940.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有