zoukankan      html  css  js  c++  java
  • poj 3281(最大流)

     题目大意就是有n头牛,f种食物,d种饮料,每头牛都有其喜欢的食物和饮料,然后每一种食物和每一种饮料只能分配给一头牛,然后如果一头牛得到了它喜欢的食物和饮料的话,该牛就得到满足,问最多可以满足多少头牛。

    这题建图非常的巧妙,最大流建图就是把食物和饮料放在两边,一头牛拆成牛左和牛右,每头牛的牛左和牛右的容量为1。每头牛喜欢的食物和该牛的牛左连边,容量为1,每头牛喜欢的饮料和该牛连边,容量为1,然后设一个源点,源点和全部食物连边,容量为1,最后设一个汇点,所以饮料和汇点连边,容量为1.这样图就建好了,跑个网络流最大流即可,我之前用的ek算法的板子在交这题时T了,所以换了个kuangbin的bfs实现的ek算法。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define inf 0x3f3f3f3f
    int mp[505][505],flow[505],path[505];
    int n,f,d,maxflow,st,et;
    
    void init()
    {
        memset(mp,0,sizeof(mp));
    
        maxflow=0;
    }
    bool bfs()
    {
        int i,t;
        queue<int>q;
        while(!q.empty()) q.pop();
        memset(path,-1,sizeof(path));
        path[st]=0;
        flow[st]=inf;
        q.push(st);
        while(!q.empty())
        {
            t=q.front();
            q.pop();
            if(t==et) break;
            for(int i=st;i<=et;i++)
            {
                if(i!=st&&path[i]==-1&&mp[t][i])
                {
                    flow[i]=min(flow[t],mp[t][i]);
                    q.push(i);
                    path[i]=t;
                }
            }
        }
        if(path[et]==-1)
            return false;
        return true;
    }
    void ek()
    {
        while(bfs())
        {
            maxflow+=flow[et];
            int now=et,pre;
            while(now!=st)
            {
                pre=path[now];
                mp[pre][now]-=flow[et];
                mp[now][pre]+=flow[et];
                now=pre;
            }
        }
    
    }
    int main()
    {
        scanf("%d%d%d",&n,&f,&d);
        init();
        st=0;
        et=f+d+2*n+1;
        for(int i=1;i<=f;i++)
            mp[st][i]=1;
        for(int i=f+2*n+1;i<=f+2*n+d;i++)
            mp[i][et]=1;
        for(int i=1;i<=n;i++)
            mp[f+2*i-1][f+2*i]=1;
        int k1,k2;
        int u;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&k1,&k2);
            while(k1--)
            {
                scanf("%d",&u);
                mp[u][f+2*i-1]=1;
            }
            while(k2--)
            {
                scanf("%d",&u);
                mp[f+2*i][f+2*n+u]=1;
            }
        }
        ek();
        printf("%d
    ",maxflow);
        return 0;
    
    }
    
  • 相关阅读:
    1.计算机初识
    re模块前瞻后顾 快速
    getattr 对类使用
    sklearn iris快速
    numpy c_
    sorted函数 字典按值倒序 实现
    logging快速入门
    configparser快速应用
    reduce 和 map 函数
    一个简单的类继承
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755031.html
Copyright © 2011-2022 走看看