poj3281(#网络流最大流)

来源:互联网 发布:土地面积测量仪软件下载 编辑:程序博客网 时间:2024/05/17 03:51
/*translation:    n头牛,f种食物,d种饮料。每头牛有各自喜欢的食物和饮料。而每种饮料和食物只能分配给一头牛。最多能够有多少头    牛可以同时得到喜欢的食物和饮料。solution:    最大流    为了保证一头牛只享有一份食物和饮料。必须把牛拆成两点。一边和对应喜欢的食物连接,一边和对应喜欢的饮料连接。    然后每条边的容量是1.求最大流即可。note:    # 一开始想错了思路,以为用二部图匹配能够做出来,思路是这样的:将牛喜欢的各自食物和饮料连起来。然后求最多      匹配。但是这样求出来的结果其实是食物和饮料的最大匹配,和最多能够分配多少头牛并没有什么联系。*/#include <iostream>#include <cstring>#include <cstdio>#include <vector>#include <queue>using namespace std;const int maxn = 500;const int INF = 0x3f3f3f3f;struct Edge{    int to, cap, rev;    Edge(int to_, int cap_, int rev_):to(to_),cap(cap_),rev(rev_){}};vector<Edge> G[maxn];vector<int> food[maxn];vector<int> drink[maxn];int level[maxn], iter[maxn];int n, f, d;void add_edge(int from, int to, int cap){    G[from].push_back(Edge(to, cap, G[to].size()));    G[to].push_back(Edge(from, 0, G[from].size() - 1));}void bfs(int s){    memset(level, -1, sizeof(level));    queue<int> que;    level[s] = 0;    que.push(s);    while(!que.empty()) {        int v = que.front();    que.pop();        for(int i = 0; i < G[v].size(); i++) {            Edge& e = G[v][i];            if(e.cap > 0 && level[e.to] < 0) {                level[e.to] = level[v] + 1;                que.push(e.to);            }        }    }}int dfs(int v, int t, int f){    if(v == t)  return f;    for(int& i = iter[v]; i < G[v].size(); i++) {        Edge& e = G[v][i];        if(e.cap > 0 && level[v] < level[e.to]) {            int d = dfs(e.to, t, min(f, e.cap));            if(d > 0) {                e.cap -= d;                G[e.to][e.rev].cap += d;                return d;            }        }    }    return 0;}int dinic(int s, int t){    int flow = 0;    for(;;) {        bfs(s);        if(level[t] < 0)    return flow;        memset(iter, 0, sizeof(iter));        int f;        while((f = dfs(s, t, INF)) > 0) {            flow += f;        }    }}int main(){    //freopen("in.txt", "r", stdin);    while(~scanf("%d%d%d", &n, &f, &d)) {        for(int i = 0; i < maxn; i++) {            G[i].clear();            food[i].clear();            drink[i].clear();        }        int fn, dn, fi, di;        for(int i = 0; i < n; i++) {            scanf("%d%d", &fn, &dn);            for(int j = 0; j < fn; j++) {                scanf("%d", &fi);   fi--;                food[i].push_back(fi);            }            for(int j = 0; j < dn; j++) {                scanf("%d", &di);   di--;                drink[i].push_back(di);            }        }        for(int i = 0; i < n; i++) {            for(int j = 0; j < food[i].size(); j++) {                for(int k = 0; k < drink[i].size(); k++) {                    add_edge(food[i][j], i + f + d, 1);                    add_edge(i + f + d + n, drink[i][k] + f, 1);                }            }        }        int s = 2 * n + f + d, t = s + 1;        for(int i = 0; i < f; i++)  add_edge(s, i, 1);        for(int i = 0; i < d; i++)  add_edge(i + f, t, 1);        for(int i = 0; i < n; i++)  add_edge(f + d + i, f + d + n + i, 1);        printf("%d\n", dinic(s, t));    }}

0 0