【图论】1459 Power Network

这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!

一、题目大意

这道题叙述的格外的麻烦,这里我就直接抽象简化的说一下了。题目大意是给你一个已知的网络,n个顶点,m条边,其中有np个发电站(只能产生电),nc的消耗站(只能消耗电),剩下的就是传输站(只能传输站)了。然后让你求这个网络的最大流。

二、题目思路以及AC代码

题目都说的很清楚了,就是求最大流的问题。但是这里是多源点多汇点求最大流的问题,不要怕,对于这个问题来说,我们可以考虑建立"超级源点"和"超级汇点","超级源点"用于给各个发电站供电,此时发电站也就相当于传输站。"超级汇点"用于消耗所有由消耗站传来的电,此时的消耗站也就相当于传输站。这样的话,整个问题就是一个最大流的模板题啦!

下面给出AC代码:

#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#define MAXN 110
#define INF 1000000
using namespace std;

int edges[MAXN][MAXN];
int pre[MAXN];
bool vis[MAXN];

int n, np, nc, nd, m;

void init() {
	for (int i = 0; i < MAXN; i++) {
		for (int j = 0; j < MAXN; j++) {
			edges[i][j] = 0;
		}
	}
}

int Min(int a, int b) {
	return a > b ? b : a;
}

void update(int t, int delta) {
	for (int i = t; pre[i] != -1; i = pre[i]) {
		edges[pre[i]][i] -= delta;
		edges[i][pre[i]] += delta;
	}
}

int find_path_bfs(int s, int t){
	memset(pre, -1, sizeof(pre));
	memset(vis, false, sizeof(vis));
	int min = INF;

	queue<int> q;
	vis[s] = true;
	q.push(s);

	while (!q.empty()) {
		int cur = q.front();	q.pop();
		
		if (cur == t) break;

		for (int i = 0; i < n + 2; i++) {
			if (!vis[i] && edges[cur][i]) {
				vis[i] = true;
				q.push(i);
				pre[i] = cur;
			}
		}
	}
	if (pre[t] == -1) return 0;

	for (int i = t; pre[i] != -1; i = pre[i]) {
		min = Min(edges[pre[i]][i], min);
	}

	return min;
}

int EK(int s, int t) {
	int new_flow = 0;
	int max_flow = 0;

	while (new_flow = find_path_bfs(s, t)) {
		update(t, new_flow);
		max_flow += new_flow;
	}
	
	return max_flow;
}

char str[100];
int main()
{
	while (scanf("%d%d%d%d", &n, &np, &nc, &m) != EOF) {
		init();

		int u, v, content;
		for (int i = 0; i < m; i++) {
			scanf("%s", str);
			sscanf(str, "(%d,%d)%d", &u, &v, &content);
			edges[u][v] += content;
		}

		for (int i = 0; i < np; i++) {
			scanf("%s", str);
			sscanf(str, "(%d)%d", &v, &content);
			edges[n][v] += content;
		}

		for (int i = 0; i < nc; i++) {
			scanf("%s", str);
			sscanf(str, "(%d)%d", &u, &content);
			edges[u][n + 1] += content;
		}

		printf("%d\n", EK(n, n + 1));
	}

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值