• POJ3281:Dining——题解


     http://poj.org/problem?id=3281

    题目大意:

    N牛,F种吃的D种喝的,牛可以在它喜欢的吃的喝的选一组,之后就不能选这个吃的喝的。

    问最多满足多少人。

    ————————————————————————————

    开始想过贼麻烦的方法,然后确认一下是否对查了题解。

    ……思想是对的,但建图建麻烦了。

    这题的关键在于如何判断奶牛和吃喝是否被用过的同时保证牛能连上他喜欢的吃喝。

    我们用对称性解决:

    奶牛拆点,左边连吃,右边连喝,喝连汇点,吃连源点。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    const int INF=2147483640;
    const int maxn=510;
    inline int read(){
        int X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    int S,T;
    struct node{
        int nxt;
        int to;
        int w;
    }edge[maxn*maxn];
    int head[maxn],cnt=-1;
    void add(int u,int v,int w){ 
        cnt++;
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].nxt=head[u];
        head[u]=cnt;
        return;
    }
    int lev[maxn],cur[maxn];
    bool bfs(int m){
        int dui[m],r=0; 
        for(int i=1;i<=m;i++){
            lev[i]=-1;
            cur[i]=head[i];
        }
        dui[0]=1,lev[1]=0;
        int u,v;
        for(int l=0;l<=r;l++){ 
            u=dui[l];
            for(int e=head[u];e!=-1;e=edge[e].nxt){
                v=edge[e].to;
                if(edge[e].w>0&&lev[v]==-1){
                    lev[v]=lev[u]+1;
                    r++;
                    dui[r]=v;
                    if(v==m)return 1;
                }
            }
        }
        return 0; 
    }
    int dinic(int u,int flow,int m){
        if(u==m)return flow;
        int res=0,delta;
        for(int &e=cur[u];e!=-1;e=edge[e].nxt){
            int v=edge[e].to;
            if(edge[e].w>0&&lev[u]<lev[v]){
                delta=dinic(v,min(edge[e].w,flow-res),m); 
                if(delta>0){
                    edge[e].w-=delta;
                    edge[e^1].w+=delta;
                    res+=delta;
                    if(res==flow)break;
                }
            }
        }
        if(res!=flow)lev[u]=-1;
        return res;
    }
    int main(){
        memset(head,-1,sizeof(head));
        int N=read();int F=read();int D=read();
        S=1;T=2*N+F+D+2;
        for(int i=1;i<=F;i++){
        add(S,i+1,1);
        add(i+1,S,0);
        }
        for(int i=1;i<=N;i++){
        int s=i+F+1,e=i+F+N+1;
        add(s,e,1);
        add(e,s,0);
        }
        for(int i=1;i<=D;i++){
        int s=i+N*2+F+1;
        add(s,T,1);
        add(T,s,0);
        }
        for(int i=1;i<=N;i++){
        int f=read();int d=read();
        for(int j=1;j<=f;j++){
            int s=read()+1;
            int e=i+F+1;
            add(s,e,1);
            add(e,s,0);
        }
        for(int j=1;j<=d;j++){
            int s=i+F+N+1;
            int e=read()+N*2+F+1;
            add(s,e,1);
            add(e,s,0);
        }
        }
        int ans=0;
        while(bfs(T))ans+=dinic(1,INF,T);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Angular2基础03: 理解依赖注入
    关于HTPP状态码的实践:307的使用
    Angular2基础03:如何重置表单的验证状态?
    Angular2基础02:模板引用变量的使用
    Angular2基础01:理解及时编译(JIT)
    cordova05:配置应用图标与启动画面
    连续子数组的最大和
    从1到整数n中1出现的次数
    滑动窗口的最大值
    矩阵中的路径
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7941891.html
Copyright © 2020-2023  润新知