2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) I 匹配,最大流

2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016)

I    题意:n个孩子,m个玩具,玩具有p个种类。每个孩子有喜欢的玩具,每个玩具有可能属于一个种类。问最多多少个孩子可以分配到一个他喜欢的玩具。

tags:SB匹配,建好图跑个最大流就好。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 1005;

int n, m, p, k, l, r, st, ed, ai;
int head[N], dis[N], tot, cur[N], remain[N<<1];
struct Edge{int to, next; } e[N<<1];
bool vis[N];
void Addedge(int u, int v, int w) {
    e[tot]=(Edge){v, head[u] }; remain[tot]=w; head[u]=tot++;
    e[tot]=(Edge){u, head[v] }; remain[tot]=0; head[v]=tot++;
}
void Init()  {
    tot=0,  st=0, ed=n+m+p+5;
    mes(head, -1);
}
bool bfs(int st, int ed)
{
    rep(i,st,ed) cur[i]=head[i];
    mes(dis, -1);
    queue<int >q;   q.push(st);  dis[st]=0;
    while(!q.empty()) {
        int u=q.front();  q.pop();
        for(int i=head[u]; i!=-1; i=e[i].next) {
            int to=e[i].to;
            if(dis[to]==-1 && remain[i]) {
                q.push(to);  dis[to]=dis[u]+1;
                if(to==ed) return true;
            }
        }
    }
    return false;
}
int dfs(int now, int ed, int flow)
{
    if(now==ed || flow==0) return flow;
    int s, ans=0;
    for(int &i=cur[now]; i!=-1; i=e[i].next) {
        int to=e[i].to;
        if(dis[to]==dis[now]+1 && (s=dfs(to,ed,min(flow, remain[i])))) {
            ans+=s, flow-=s;
            remain[i]-=s, remain[i^1]+=s;
            if(flow==0) break;
        }
    }
    return ans;
}
int dinic(int st, int ed)
{
    int s, ans=0;
    while(bfs(st,ed))  while(s=dfs(st,ed,INF))  ans+=s;
    return ans;
}
int main()
{
    scanf("%d %d %d", &n, &m, &p);
    Init();
    rep(i,1,n) {
        scanf("%d", &k);
        rep(j,1,k) scanf("%d", &ai), Addedge(i, ai+n, 1);
        Addedge(st, i, 1);
    }
    mes(vis,0);
    rep(i,1,p) {
        scanf("%d", &l);
        rep(j,1,l) scanf("%d", &ai), Addedge(ai+n, i+n+m, 1), vis[ai]=1;
        scanf("%d", &r); Addedge(i+n+m, ed, r);
    }
    rep(i,1,m) if(vis[i]==0) Addedge(i+n, ed, 1);
    printf("%d\n", dinic(st, ed));

    return 0;
}
View Code

 

posted @ 2017-07-08 21:04  v9fly  阅读(477)  评论(0编辑  收藏  举报