POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料

Posted lighten-up-belief

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",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\n",u,v,tmp);
            e[i].flow +=   tmp;
            e[i^1].flow -= tmp;

            exp-=tmp;
            flow+=tmp;

            if(exp==0) break;
        
    
    //pt("wt\n");
    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\n");
        int i,j,ans=0,u,v,tt,FF,DD;
        init(); s=0,t=1+2*N+F+D;
    //    pt("OK\n");
        // 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\n");
        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\n");
        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\n",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\n",tt);
            
        
        pt("%d\n",ans);
    
    return 0;
POJ 3281

 

以上是关于POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3281 Dining (拆点)最大流

poj 3281 Dining(网络流+拆点)

POJ 3281(Dining-网络流拆点)[Template:网络流dinic]

POJ-3281 Dining 最大流 拆点

poj3281网络流之最大流

poj3281Dining——网络流匹配