POJ 3281 Dining(网络流最大匹配)

分析

数学模型是三个集合A,B,C,(a,b,c)构成一个匹配。因为图一个点只能匹配一次,把a拆点a',a",

在可以匹配的点上连边,s - b - a' - a" - c - t,然后最大流就好了。

/*********************************************************
*            ------------------                          *
*   author AbyssalFish                                   *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long ll;

const int maxv = 402, maxe = 40600+2;
int hd[maxv],to[maxe],nx[maxe],ec, cap[maxe];
#define eachEage int i = hd[u]; i; i = nx[i]
void add(int u,int v,int cp)
{
    nx[++ec] = hd[u];
    to[ec] = v;
    cap[ec] = cp;
    hd[u] = ec;
}
void Add(int u,int v,int cp = 1)
{
    add(u,v,cp);
    add(v,u,0);
}

int S,T;

int lv[maxv];
bool vis[maxv];
int que[maxv];

bool bfs()
{
    memset(vis,0,sizeof(vis));
    int *q = que, l = 0, r = 0;
    lv[q[r++] = S] = 0; vis[S] = true;
    while(l<r){
        int u = q[l++];
        for(eachEage){
            int v = to[i];
            if(!vis[v] && cap[i]){
                lv[v] = lv[u] + 1;
                vis[v] = true;
                q[r++] = v;
            }
        }
    }
    return vis[T];
}

int cur[maxv];

int aug(int u,int a)
{
    if(u == T || !a) return a;
    int flow = 0,f;
    for(int &i = cur[u]; i; i = nx[i]){
        int v = to[i];
        if(lv[v] == lv[u]+1 && (f = aug(v,min(a,cap[i])))){
            flow += f; a -= f;
            cap[i] -= f; cap[i^1] += f;
            if(!a) break;
        }
    }
    return flow;
}

int maxFlow()
{
    int flow = 0;
    while(bfs()){
        memcpy(cur,hd,sizeof(int)*(T+1));
        flow += aug(S,1<<30);
    }
    return flow;
}

//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    ec = 1;
    int N, F, D; scanf("%d%d%d",&N,&F,&D);
    int N2 = N*2, N2F = N2+F;
    S = 0; T = N2F+D+1;
    for(int i = 1; i <= N; i++){
        int Fi, Di, x; scanf("%d%d",&Fi,&Di);
        while(Fi--){
            scanf("%d", &x);
            Add(N2+x,i);
        }
        Add(i,N+i);
        while(Di--){
            scanf("%d", &x);
            Add(N+i,N2F+x);
        }
    }
    for(int i = 1; i <= F; i++) Add(S,N2+i);
    for(int i = 1; i <= D; i++) Add(N2F+i,T);
    printf("%d
", maxFlow());
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4947539.html