zoukankan      html  css  js  c++  java
  • POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料

      如何建图?

      最开始的问题就是,怎么表示一只牛有了食物和饮料呢?

      后来发现可以先将食物与牛匹配,牛再去和饮料匹配,实际上这就构成了三个层次。

      起点到食物层边的容量是1,食物层到奶牛层容量是1,奶牛层到饮料层容量是1,饮料层到终点容量是1。

      但是后来发现有一组hack数据:

      2 3 3

      3 3 1 2 3 1 2 3
      3 3 1 2 3 1 2 3

      我们发现一头奶牛居然吃了多个套餐,所以要解决这个只需要将自己与自己建立一条容量是1的边就行了。

      

    #include <cstdio>
    #include <cstring>
    #include <stack>
    using namespace std;
    #define sc scanf 
    #define pt printf
    #define maxe 40960
    #define maxv 405
    #define maxn 1000
    #define mll long long
    const int inf = 0x3f3f3f3f;
    int mn(int a,int b) { return a<b?a:b; }
    int  s,t, N,F,D;
    typedef struct ed{
        int v,w,cap,flow;
    } ed;
    ed e[maxe];
    int head[maxv],nxt[maxe],tot,dis[maxv];
    void init()
    {
        tot = 0 ; 
        memset(head,-1,sizeof(head));
    }
    
    void add(int u,int v,int cap,int flow)
    {
        e[tot].v=v;
        e[tot].cap=cap; 
        e[tot].flow=flow;
        nxt[tot]=head[u];
        head[u]=tot++;
    
        e[tot].v=u;
        e[tot].cap=flow;        
        e[tot].flow=0;
        nxt[tot]=head[v];
        head[v]=tot++;
    }
    int dfs(int u,int exp)
    {
        if(exp==0||u==t) return exp;
        int i,v,flow=0,tmp;
        for(i=head[u];i!=-1;i=nxt[i])
        {
            v=e[i].v;
            //pt("u=%d,v=%d
    ",u,v);
            
            if(dis[v]==dis[u]+1)
            {
                tmp = dfs(v,mn(e[i].cap-e[i].flow,exp));
                if(tmp==0) continue;
                // pt("u=%d,v=%d,tmp=%d
    ",u,v,tmp);
                e[i].flow +=   tmp;
                e[i^1].flow -= tmp;
    
                exp-=tmp;
                flow+=tmp;
    
                if(exp==0) break;
            }
        }
        //pt("wt
    ");
        if(flow==0) dis[u]=inf;
        return flow;
    }
    stack<int> q;
    int main()
    {
        freopen("in.txt","r",stdin);
        while(~sc("%d%d%d",&N,&F,&D))
        {
            //pt("OK
    ");
            int i,j,ans=0,u,v,tt,FF,DD;
            init(); s=0,t=1+2*N+F+D;
        //    pt("OK
    ");
            // F使用1-F  N使用(F+1 - F+N)(F+1 + N - F+ 2*N)  D使用 F+2*N+1 - F+2*N+D
            for(i=1;i<=F;++i) add(0,i,1,0);
            for(i=F+2*N+1;i<=F+2*N+D;++i) add(i,t,1,0);
            for(i=F+1;i<=F+N;++i) add(i,i+N,1,0);
            //pt("OK
    ");
            for(i=1;i<=N;++i)
            {
                sc("%d%d",&FF,&DD);
                for(j=1;j<=FF;++j)
                {
                    sc("%d",&tt);
                    add(tt,F+i,1,0);
                }  
                for(j=1;j<=DD;++j)
                {
                    sc("%d",&tt);
                    add(F+N+i,F+2*N+tt,1,0);
                }  
            }
            //pt("OK
    ");
            while(1)
            {
                //BFS建立层次图
                memset(dis,inf,sizeof(dis));
                dis[s]=0; 
                while(!q.empty()) q.pop();
                q.push(s);
                while(!q.empty())
                {
                    
                    u=q.top(); q.pop();
                    for(i=head[u];i!=-1;i=nxt[i])
                    {
                        if(e[i].cap - e[i].flow <= 0) continue;
                        v = e[i].v;
                        
                        if(dis[u]+1<dis[v])
                        {
                            dis[v] = dis[u] +1;
                            //pt("BFS: u=%d,v=%d
    ",u,v);
                            if(v==t) break;
                            q.push(v);
                        } 
                        
                    }
                }
                if(dis[t]==inf) break;
                //DFS进行增广
                tt=dfs(0,inf);
                if(tt==0) break;
                else ans+=tt;
                //pt("tt=%d
    ",tt);
                
            }
            pt("%d
    ",ans);
        }
        return 0;
    }
    POJ 3281
  • 相关阅读:
    前端面试题总结(js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)
    steps 步骤条、时间轴
    碰撞检测经典解决方案
    延迟渲染(Deferred Shading)技术详解
    配备透明触摸屏 看3D全息投影概念手机
    预渲染技术
    APK改之理(APK IDE)修改APK简单的入门教程
    如何获取显卡的GPU占用率和显存占用情况
    图像编辑之对比度调整 亮度对比度的算法公式
    别被你的双眼所欺骗 100张神奇的视觉欺骗图
  • 原文地址:https://www.cnblogs.com/lighten-up-belief/p/11332102.html
Copyright © 2011-2022 走看看