1003. Universal Travel Sites (35)解题报告

思路

这道题实际上是在问图算法中的最大流问题,使用Edmonds-Karp算法就可以解决。

它的时间复杂度是O(VE^2)。具体的算法和证明请参考《算法导论》第六部分图算法第26章最大流。

还有比EK算法时间上更加优越的方法,具体也请参考《算法导论》相同部分,这里我就不细说了。

另外感谢:点击打开链接

通过画面

 

代码

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <climits>
using namespace std;

struct edge {
	char source[4], dest[4];
	int capacity, s, d;
	int dindex(void) {
		int index = 0;
		index = ((dest[0] - 'A') * 26 + dest[1] - 'A') * 26 + dest[2] - 'A';
		return index;
	}
	int sindex(void) {
		int index = 0;
		index = ((source[0] - 'A') * 26 + source[1] - 'A') * 26 + source[2] - 'A';
		return index;
	}
	void read(void) {
		scanf("%s %s %d", source, dest, capacity);
		return;
	}
};

const int MAX = 26 * 26 * 26;

bool BFS(vector<edge> arr[], int route[], int source, int dest);
int Edmonds_Karp(vector<edge> arr[], int source, int dest);

int main(void) {
	int i, j, n, sindex, dindex;
	edge tmp;
	vector<edge> *arr;
	setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20);
	scanf("%s %s %d", tmp.source, tmp.dest, &n);
	sindex = tmp.sindex();
	dindex = tmp.dindex();
	arr = new vector<edge>[MAX];
	for (i = 0; i < n; i++) {
		scanf("%s %s %d", tmp.source, tmp.dest, &tmp.capacity);
		tmp.s = tmp.sindex();
		tmp.d = tmp.dindex();
		arr[tmp.s].push_back(tmp);
	}
	
	printf("%d", Edmonds_Karp(arr, sindex, dindex));
	delete[] arr;
	return 0;
}

bool BFS(vector<edge> arr[], int route[], int source, int dest) {
	bool *visit = (bool *)calloc(MAX, sizeof(bool));
	int i, j;
	queue<int> q;
	q.push(source);
	visit[source] = true;
	while (!q.empty()) {
		i = q.front();
		q.pop();
		if (i == dest) {
			break;
		}
		for (auto vit : arr[i]) {
			j = vit.d;
			if (!visit[j] && vit.capacity > 0) {
				q.push(j);
				route[j] = i;
				visit[j] = true;
			}
		}
	}
	free(visit);
	return i == dest ? true : false;
}

int Edmonds_Karp(vector<edge> arr[], int source, int dest) {
	int c, *route, i, j, max, f;
	vector<edge>::iterator vit;
	route = new int[MAX];
	max = 0;
	for (i = 0; i < MAX; i++) {
		route[i] = -1;
	}
	while (BFS(arr, route, source, dest)) {
		f = INT_MAX;
		for (i = dest; i != source;) {
			j = route[i];
			for (vit = arr[j].begin(); vit != arr[j].end(); vit++) {
				if (vit->d == i) {
					f = min(f, vit->capacity);
					break;
				}
			}
			i = j;
		}
		for (i = dest; i != source;) {
			j = route[i];
			for (vit = arr[j].begin(); vit != arr[j].end(); vit++) {
				if (vit->d == i) {
					vit->capacity -= f;
					break;
				}
			}
			i = j;
		}
		max += f;
		for (i = 0; i < MAX; i++) {
			route[i] = -1;
		}
	}
	delete[] route;
	return max;
}

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值