P1231 教辅的组成 拆点限流

如果只有两个物品的话 是一个裸的二分图匹配问题

现在变成了三个物品之间的匹配 则只要在中间加一层节点表示书 再把这层的每个点拆成两个点中间连一条边限制流量 使其只能用一次

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define REP(i, a, b) for(register int i = (a), i##_end_ = (b); i <= i##_end_; ++ i)
#define DREP(i, a, b) for(register int i = (a), i##_end_ = (b); i >= i##_end_; -- i)
#define mem(a, b) memset((a), b, sizeof(a))
int read()
{
    int sum = 0, fg = 1; char c = getchar();
    while(c < '0' || c > '9') { if (c == '-') fg = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { sum = sum * 10 + c - '0'; c = getchar(); }
    return sum * fg;
}
#define inf 0x3f3f3f3f
const int maxn = 1000000;
int e,be[maxn], ne[maxn], to[maxn], c[maxn];
int nb, nex, na,m1,m2;
void add(int x, int y, int z)
{
    to[e] = y, ne[e] = be[x], be[x] = e;
    c[e] = z, e++;
    to[e] = x, ne[e] = be[y], be[y] = e;
    c[e] = 0, e++;
}
int d[maxn], end;
bool bfs()
{    
    queue<int>q;
    memset(d,-1,sizeof(d));
    q.push(end),d[end] = 0;
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int i = be[u]; i!=-1; i = ne[i])
        {
            int v = to[i];
            if(d[v] == -1 && c[i ^ 1])
            {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d[0]!=-1;
}
int dfs(int x,int low)
{
    if(x == end || !low)return low;
    int ret = 0;
    for(int i = be[x]; i!=-1;i = ne[i])
    {
        int v = to[i];
        if(d[v] == d[x] - 1 )
        {
            int    k = dfs(v,min(low-ret,c[i]));
            if(k > 0)
            {
                c[i] -= k;
                c[i^1] += k;
                ret+=k;
            }
        }
    }
    return ret;
}
int dinic()
{
    int ans = 0;
    while(bfs())
    {
        int k = dfs(0,inf);
        if(k>0)ans+=k;
    }
    return ans;
}
int main()
{
    memset(be,-1,sizeof(be));    
    nb = read(); nex = read(); na = read();
    m1 = read();
    REP(i,1,m1)
    {
        int x,y;
        x = read(), y = read();
        add(y,nex+x,1);
    }
    m2 = read();
    REP(i,1,m2)
    {
        int x,y;
        x = read(), y = read();
        add(nex+nb+x,2*nb+nex+y,1);
    }
    end = 2*nb+nex+na+1;
    REP(i,1,nex)    add(0,i,1);
    REP(i,1,na) add(2*nb+nex+i,end,1);
    REP(i,1,nb) add(nex+i,nex+nb+i,1);
    printf("%d",dinic());
    return 0;
}
View Code

 

posted @ 2019-04-03 13:09  Aragaki  阅读(174)  评论(0编辑  收藏  举报