码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3281 Dining

时间:2017-05-01 12:00:52      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:nic   一点   name   最大   scanf   dinic   max   return   while   

传送门:https://vjudge.net/problem/POJ-3281

技术分享

技术分享

题目大意:

这儿的主人公是N头牛,和一个农场主。每头牛都有一个特别的食谱,这是他们喜欢吃的食物和饮料。农场主准备了F种食物,和D种饮料。他想要尽可能多的牛都能都的到自己喜欢吃的食物和饮料(注每头牛只需要一份食物和一份饮料)。问这样的牛最少数量是多少。

 

解题思路:

这是一个最大流的题。我门可以建立如下的图。

 技术分享

 

哈哈上面的是错误的。

技术分享

具体为什么,自己想一下就知道了,主要是在建图的时候有一点麻烦。

实现代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;

const int MAXN=5000;
const int INF=1<<30;
int N,F,D;

struct Edge{
    int to,next;
    int cap;
    Edge(int to,int next,int cap):to(to),next(next),cap(cap){};
    Edge(){};
}edges[MAXN];

int head[MAXN];
int tot;
void init(){
    memset(head,-1,sizeof(head));
    tot=0;
}

void addEdge(int u,int v,int cap){
    edges[tot].to=v;
    edges[tot].cap=cap;
    edges[tot].next=head[u];
    head[u]=tot++;
}


void initGraph(int s,int t){
    for(int i=1;i<=F;i++){
        addEdge(s,i,1);
        addEdge(i,s,0);
    }
    for(int i=1;i<=N;i++){
        addEdge(F+i,F+N+i,1);
        addEdge(F+N+i,F+i,0);
    }
    for(int i=1;i<=D;i++){
        addEdge(F+2*N+i,t,1);
        addEdge(t,F+2*N+i,0);
    }
}

int level[MAXN];
bool makelevel(int s,int t){
    //cout<<"-----------"<<endl;
    memset(level,0,sizeof(level));
    level[s]=1;
    queue<int>q;
    q.push(s);

    while(!q.empty()){
        int u=q.front();q.pop();
        if(u==t) return true;
        for(int i=head[u];i!=-1;i=edges[i].next){
            int v=edges[i].to;
            if(!level[v]&&edges[i].cap){
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return false;
}

int dfs(int now,int maxf,int t){
    if(now==t) return maxf;
    int ret=0,f;

    for(int i=head[now];i!=-1;i=edges[i].next){
        int v=edges[i].to;
        if(edges[i].cap&&level[v]==level[now]+1){
            f=dfs(v,min(maxf-ret,edges[i].cap),t);
            edges[i].cap-=f;
            edges[i^1].cap+=f;
            ret+=f;
        }
        if(ret==maxf)
            return ret;
    }
    return ret;
}

int Dinic(int s,int t){
    int ans=0;
    while(makelevel(s,t))
        ans+=dfs(s,INF,t);
    return ans;
}
int  main(){
    scanf("%d%d%d",&N,&F,&D);
    init();
    initGraph(0,F+N+N+D+1);

    for(int i=1;i<=N;i++){
        int CF,CD;
        scanf("%d%d",&CF,&CD);
        for(int j=0;j<CF;j++){
            int TF;
            scanf("%d",&TF);
            addEdge(TF,F+i,1);
            addEdge(F+i,TF,0);
        }

        for(int j=0;j<CD;j++){
            int TD;
            scanf("%d",&TD);
            addEdge(F+N+i,TD+F+N+N,1);
            addEdge(TD+F+N+N,F+N+i,0);
        }
    }
    /*cout<<endl;
    for(int i=0;i<=F+N+N+D+1;i++){
        cout<<i<<"  ";
        for(int j=head[i];j!=-1;j=edges[j].next)
            cout<<edges[j].to<<"("<<edges[j].cap<<")  ";
        cout<<endl;
    }*/
    cout<<Dinic(0,F+N+N+D+1)<<endl;
    return 0;
}

 

POJ 3281 Dining

标签:nic   一点   name   最大   scanf   dinic   max   return   while   

原文地址:http://www.cnblogs.com/IKnowYou0/p/6791506.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!