UVA 12264 二分+最大流 基础题

来源:互联网 发布:阿里云幕布如何申请 编辑:程序博客网 时间:2024/06/06 05:52

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

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

#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;}