HDU 4292:Food(最大流)

http://acm.hdu.edu.cn/showproblem.php?pid=4292

题意:和奶牛一题差不多,只不过每种食物可以有多种。

思路:因为食物多种,所以源点和汇点的容量要改下。还有Dinic又TLE了,用ISAP过。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
#define N 910
typedef long long LL;
typedef long long LL;
struct Edge {
    int v, cap, nxt;
    Edge () {}
    Edge (int v, int cap, int nxt) : v(v), cap(cap), nxt(nxt) {}
}edge[N*N];
int tot, cur[N], dis[N], pre[N], head[N], gap[N], S, T;

void Add(int u, int v, int cap) {
    edge[tot] = Edge(v, cap, head[u]); head[u] = tot++;
    edge[tot] = Edge(u, 0, head[v]); head[v] = tot++;
}

void BFS() {
    queue<int> que;
    while(!que.empty()) que.pop();
    memset(dis, -1, sizeof(dis));
    memset(gap, 0, sizeof(gap));
    dis[T] = 0; gap[0]++; que.push(T);
    while(!que.empty()) {
        int u = que.front(); que.pop();
        for(int i = head[u]; ~i; i = edge[i].nxt) {
            int v = edge[i].v;
            if(dis[v] == -1) continue;
            dis[v] = dis[u] + 1;
            gap[dis[v]]++;
            que.push(v);
        }
    }
}

int ISAP(int n) {
    memcpy(cur, head, sizeof(cur));
    BFS();
    int u = pre[S] = S, ans = 0, i;
    while(dis[S] < n) {
        if(u == T) {
            int flow = INF, index;
            for(int i = S; i != T; i = edge[cur[i]].v) {
                Edge& e = edge[cur[i]];
                if(e.cap < flow) {
                    flow = e.cap; index = i;
                }
            }
            for(int i = S; i != T; i = edge[cur[i]].v) {
                edge[cur[i]].cap -= flow;
                edge[cur[i]^1].cap += flow;
            }
            ans += flow; u = index;
        }
        for(i = cur[u]; ~i; i = edge[i].nxt)
            if(dis[edge[i].v] == dis[u] - 1 && edge[i].cap > 0)
                break;
        if(~i) {
            cur[u] = i;
            pre[edge[i].v] = u;
            u = edge[i].v;
        } else {
            int md = n;
            if(--gap[dis[u]] == 0) break;
            for(int i = head[u]; ~i; i = edge[i].nxt) {
                if(md > dis[edge[i].v] && edge[i].cap > 0) {
                    md = dis[edge[i].v]; cur[u] = i;
                }
            }
            ++gap[dis[u] = md + 1];
            u = pre[u];
        }
    }
    return ans;
}

int main() {
    int n, f, d;
    while(~scanf("%d%d%d", &n, &f, &d)) {
        S = 0, T = 2 * n + f + d + 1;
        memset(head, -1, sizeof(head));
        tot = 0; int a; char s[500];
        for(int i = 1; i <= f; i++) {
            scanf("%d", &a);
            Add(S, i + 2 * n, a);
        }
        for(int i = 1; i <= d; i++) {
            scanf("%d", &a);
            Add(i + 2 * n + f, T, a);
        }
        for(int i = 1; i <= n; i++) {
            Add(i, i + n, 1);
            scanf("%s", s + 1);
            for(int j = 1; j <= f; j++) {
                if(s[j] == 'Y') {
                    Add(2 * n + j, i, 1);
                }
            }
        }
        for(int i = 1; i <= n; i++) {
            scanf("%s", s + 1);
            for(int j = 1; j <= d; j++) {
                if(s[j] == 'Y') {
                    Add(i + n, 2 * n + j + f, 1);
                }
            }
        }
        printf("%d
", ISAP(T + 1));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/fightfordream/p/6237100.html