UVA 12264 二分+最大流 基础题

题意略坑,不解释。 看懂了水题一道。

也不算什么中等题,简单题罢了,随便保存一下代码。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 410;
const int inf = 1e9;
struct Edge {
	int v, c, next;
	Edge(){}
	Edge(int v, int c, int next): v(v), c(c), next(next) {}
}edge[1000006];

int head[maxn], E;
int n, m;
int S, T;

void init() {
    E = 0;
    memset(head, -1, sizeof(head));
}
void add(int s, int t, int c) {
	edge[E] = Edge(t, c, head[s]);
	head[s] = E++;
	edge[E] = Edge(s, 0, head[t]);
	head[t] = E++;
}

int gap[maxn], dis[maxn], pre[maxn], cur[maxn];
int sap(int s, int t, int n) {
	int i;
	for(i = 0; i <= n; i++) {
		cur[i] = head[i];
		gap[i] = dis[i] = 0;
	}
	gap[0] = n;
	int u = pre[s] = s, maxf = 0, v, aug = inf;
	while(dis[s] < n) {
		loop:for(i = cur[u]; ~i; i = edge[i].next) {
			v = edge[i].v;
			if(edge[i].c && dis[u] == dis[v]+1) {
				pre[v] = u;
				cur[u] = i;
				aug = min(aug, edge[i].c);
				u = v;
				if(u == t) {
					while(u != s) {
						u = pre[u];
						edge[cur[u]].c -= aug;
						edge[cur[u]^1].c += aug;
					}
					maxf += aug;
					aug = inf;
				}
				goto loop;
			}
		}
		int d = n;
		for(i = head[u]; ~i; i= edge[i].next) {
			v = edge[i].v;
			if(edge[i].c && dis[v] < d) {
				d = dis[v];
				cur[u] = i;
			}
		}
		if(!(--gap[dis[u]])) break;
		++gap[dis[u] = d+1];
		u = pre[u];
	}
	return maxf;
}
int a[maxn];
char mp[maxn][maxn];
int sum, ans;

void build(int m) {
	int i, j;
	sum = 0;
	init();
	for(i = 0; i < n; i++)
		if(a[i]) {
			add(S, i, a[i]);
			add(i, i+n, a[i]);
		}
	for(i = 0; i < n; i++) if(a[i]) {
		bool g = 0;
		for(j = 0; j < n; j++) if(mp[i][j] == 'Y'){
			if(a[j]) add(i, j+n, inf);
			else g = 1;
		}
		if(!g) add(i+n, T, 1), sum++;
		else add(i+n, T, m), sum += m;
	}
}
int main() {
	int i, j, cas;
	scanf("%d", &cas);
	for(int ca = 1; ca <= cas; ca++) {
		scanf("%d", &n);
		for(i = 0; i < n; i++) scanf("%d", &a[i]);
		for(i = 0; i < n; i++)
			scanf("%s", mp[i]);
		S = 2*n; T = S+1;
		int l = 1, r = 10000;
		while(l <= r) {
			int mid = l+r>>1;
			build(mid);
			int tp = sap(S, T, T+1);
			if(tp < sum) r = mid-1;
			else {
				ans = mid;
				l = mid+1;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}


你可能感兴趣的:(UVA 12264 二分+最大流 基础题)