您的位置:首页 > 其它

POJ-3281 Dining(最大流)

2017-12-07 22:46 375 查看
  题目:POJ-3281 Dining

  题目大意:一个农场场主,为他的n头牛做了f种食物和d种饮料,每头牛都有他喜欢的食物和饮料,而且,每个食物或饮料都只能给一头牛食用,问最多能同时满足多少头牛的饮食。

  解题思路:这个题目我只记得我一开始看网络流的时候看到过,当时这个构图并不会,但现在看起来好像就没当初那么难了。这个题目如果只有食物和牛的话就有点二分图的意思了,可是加了喜欢的饮料,所以需要网络流做。难点当然在构图,看到这个题目的第一感觉是从源点到牛有边权值为2表示一头牛需要两样东西满足,牛到喜欢的饮料和食物分别有边权值为1,然后食物饮料到汇点有边权值为1表示只能有一个牛使用,然后看看最大流的流值的一半就是牛的个数,但是明显不对,因为2个流值可能不同属于一头牛,但是最直观的想法往往可以反应问题,不过需要更加苛刻的限制,这样就想到了一牛一流,也就是食物连牛,权值为1,牛连饮料,权值为1,食物饮料分别连接原点和汇点,权值都是1。构图完成,流的最大值就是牛的个数。

  AC代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<queue>

#include<cmath>

#include<vector>

#define maxn 510

#define INF 1e9

using namespace std;

struct edge{

    edge(){};

    edge(int from,int to,int val,int flow):from(from),to(to),val(val),flow(flow){}

    int from,to,val,flow;

};

int n,m,f,d;

vector<edge>p;

vector<int>num[maxn];

bool visit[maxn];

int dis[maxn];

int cur[maxn];

void add(int x,int y,int z){

    p.push_back(edge(x,y,z,0));

    p.push_back(edge(y,x,0,0));

    int xx=p.size();

    num[x].push_back(xx-2);

    num[y].push_back(xx-1);

}

bool bfs(int s,int t){

    int i,j;

    memset (visit,0,sizeof(visit));

    queue<int>qq;

    qq.push(s);

    dis[s]=0;

    visit[s]=1;

    while (!qq.empty()){

        int u=qq.front();

        qq.pop();

        for (i=0;i<num[u].size();i++){

            edge& e=p[num[u][i]];

            if (!visit[e.to]&&e.val>e.flow){

                visit[e.to]=1;

                dis[e.to]=dis[u]+1;

                qq.push(e.to);

            }

        }

    }

    return visit[t];

}

int dfs(int x,int t,int val){

    if (x==t||val==0){

        return val;

    }

    int flow=0,f;

    for (int& i=cur[x];i<num[x].size();i++){

        edge& e=p[num[x][i]];

        if (dis[x]+1==dis[e.to]&&(f=dfs(e.to,t,min(val,e.val-e.flow)))>0){

            e.flow+=f;

            p[num[x][i]^1].flow-=f;

            flow+=f;

            val-=f;

            if (val==0)break;

        }

    }

    return flow;

}

int dinic(int s,int t){

    int flow=0;

    while (bfs(s,t)){

        memset (cur,0,sizeof(cur));

        flow+=dfs(s,t,INF);

    }

    return flow;

}

int main(){

    int i,j,k,l,x,y,z,t;

    while (scanf("%d%d%d",&n,&f,&d)!=EOF){

        int total=2*n+d+f+1;

        for (i=1;i<=f;i++)add(0,i,1);

        for (i=1;i<=d;i++)add(i+2*n+f,total,1);

        for (i=1+f;i<=n+f;i++){

            add(i,n+i,1);

            scanf("%d%d",&x,&y);

            while (x--){

                scanf("%d",&z);

                add(z,i,1);

            }

            while (y--){

                scanf("%d",&z);

                add(n+i,z+2*n+f,1);

            }

        }

        printf("%d\n",dinic(0,total));

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: