POJ3281

来源:互联网 发布:mac os x dmg 下载 编辑:程序博客网 时间:2024/05/16 10:18

Problem : Dining
Description : 有一些奶牛,他们都有自己喜欢的一些食物和饮料。要你求最多有多少头奶牛既拿到自己喜欢的食物也拿到自己喜欢的饮料。一种食物或饮料只能提供给某一头奶牛,而一头奶牛也只能享用一种食物或一种饮料
Solution : 网络最大流。如果能想到网络最大流,那么就能想到怎么构图了,既然既要拿到食物也要拿到饮料,那么我们就把奶牛放到食物和饮料中间,这样,就把食物奶牛和饮料联系起来了。然后跑一遍最大流就好了,但是这里要注意的是。牛要拆点。这是为什么呢,一开始我就错在了这里,原因是上面加粗的文字。如果拆点之后加边,就能满足一头奶牛只能享用一种食物和饮料了。自己画个图就明白了。
Code(C++) :

#include <stdio.h>#include <string.h>#include <iostream>#include <string>#include <queue>#define MIN(a,b) ((a)>(b)? (b):(a))using namespace std;const int SIZE=400+50;const int INF=0x3f3f3f3f;int src,des;int map[SIZE][SIZE];int d[SIZE];int n;int N,F,D;void build(){    int i;    n=2*N+F+D;    src=0;    des=n+1;    memset(map,0,sizeof(map));    for(i=1;i<=F;i++)        map[src][i]=1;    for(i=1;i<=D;i++)        map[F+2*N+i][des]=1;    for(i=1;i<=N;i++)        map[F+i][F+N+i]=1;    int F0,D0;    for(i=1;i<=N;i++){        scanf("%d%d",&F0,&D0);        int x,j;        for(j=1;j<=F0;j++)            scanf("%d",&x),            map[x][F+i]=1;        for(j=1;j<=D0;j++)            scanf("%d",&x),            map[F+N+i][F+2*N+x]=1;    }}bool bfs(int src,int des){    memset(d,-1,sizeof(d));    queue<int> que;    que.push(src);    d[src]=0;    while(!que.empty()){        int now=que.front();        que.pop();        for(int i=0;i<=1+n;i++)            if(d[i]==-1&&map[now][i]>0){                d[i]=d[now]+1;                que.push(i);            }    }    return d[des]>=0;}int dfs(int t,int sum,int des){    if(t==des)        return sum;    int tmp=sum;    for(int i=0;i<=n+1&&sum;i++)        if(d[i]==d[t]+1&&map[t][i]>0){            int a=dfs(i,MIN(sum,map[t][i]),des);            map[t][i]-=a;            map[i][t]+=a;            sum-=a;        }    return tmp-sum;}int DINIC(int src,int des){    int sum=0;    while(bfs(src,des))        sum+=dfs(src,INF,des);    return sum;}int main(){    //freopen("in.data","r",stdin);    while(~scanf("%d%d%d",&N,&F,&D)){        build();        printf("%d\n",DINIC(src,des));    }    return 0;}
0 0
原创粉丝点击