奶牛食品 (网络流) gzoi

广州的同学看这里:

http://www.gdgzoi.com/JudgeOnline/problem.php?cid=1045&pid=1

Description

FJ的奶牛们只吃各自喜欢的一些特定的食物和饮料,除此之外的其他食物和饮料一概不吃。某天FJ为奶牛们精心准备了一顿美妙的饭食,但在之前忘记检查奶牛们的菜单,这样显然是不能不能满足所有奶牛的要求。但是FJ又不愿意为此重新来做,所以他他还是想让尽可能多的牛吃到他们喜欢的食品和饮料。

FJ提供了F (编号为1、2、…、F)种食品并准备了D (编号为1、2、…、D)种饮料, 他的N头牛(编号为1、2、…、N)都已决定了是否愿意吃某种食物和喝某种饮料。FJ想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料。

每一种食物和饮料只能由一头牛来用。例如如果食物2被一头牛吃掉了,没有别的牛能吃到食物2。

输入第一行包含三个用空格分开的整数N,F和D;接下来的N行描述每个奶牛的信息:第i+1行的前两个整数为F_i和D_i,接下来的F_i个整数表示奶牛i喜欢的食品编号,再接下来的D_i个整数表示奶牛i喜欢的饮料编号。

输出仅一行一个整数,表示FJ最多能让多少头奶牛吃到自己喜欢的食品和饮料。

样例

Dining.in

Dining.out

4 3 3

扫描二维码关注公众号,回复: 2950008 查看本文章

2 2 1 2 3 1

2 2 2 3 1 2

2 2 1 3 1 2

2 1 1 3 3

3

 

样例说明

输入数据表明:奶牛1喜欢的食物1、2;喜欢喝饮料3、1;奶牛2喜欢的食物2、3;喜欢喝饮料1、2;奶牛3喜欢的食物1、3;喜欢喝饮料1、2;奶牛4喜欢的食物1、3;喜欢喝饮料3;

那么下面的分配方法将是最优的:奶牛1不给食品和饮料;奶牛2分配食物2和饮料2;奶牛3分配食物1和饮料2;奶牛4分配食物3和饮料3。

【数据范围】

1<=F<=100,1<=D<=100,1<=N<=100

非常典型的网络流问题

下面是建图方法:

1.建一个超源点连接每一种食物容量为1。

2.将每种食物和奶牛连接起来:把奶牛拆成两个点,一个连接食物容量1,一个连接饮料容量1,再把这俩点连接,容量为1;

3.最后再把饮料与超汇点连接起来容量为1;

这样就保证了一牛,一食,一饮料。

 

接下来就是贴码的时候了:

mdzz数据太弱我这个蒟蒻没有拆牛(不,是压根没牛竟然过了)

代码仅供参考(千万别学我的苟数据)

 

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cstring>
#define maxn 205
#define INF  2
using namespace std;
struct edg{
   int from,to,cap,flow;
   edg(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {}
};
   int a[maxn];
   int p[maxn];
 
vector<int> G[maxn];
vector<edg> edges;
bool GG[maxn][maxn]; 
 
   void AddEdge(int u,int v){
    edges.push_back(edg(u,v,1,0));
    edges.push_back(edg(v,u,0,0));
    int num=edges.size();
    G[u].push_back(num-2);
    G[v].push_back(num-1);
    GG[u][v]=true;
}  
 
int Maxflow(int s,int t)
{int flow=0;
    for(;;){
        memset(a,0,sizeof(a));
         queue<int> Q;
          Q.push(s);a[s]=INF;       
            while(!Q.empty()){
                int x=Q.front();Q.pop();
                for(unsigned int i=0;i<G[x].size();i++) {
                    edg& e=edges[G[x][i]];
                    if(!a[e.to] && e.cap>e.flow){
                        p[e.to]=G[x][i];
                        a[e.to]=min(a[x],e.cap-e.flow);
                        Q.push(e.to);
                    }
                    if(a[t]!=0) break;
                    }
                }
                    if(a[t]==0) break;
                    for(int i=t;i!=s;i=edges[p[i]].from){
                        edges[p[i]].flow+=a[t];
                         edges[p[i]^1].flow-=a[t];}
                         flow+=a[t];
                    }
                    return flow;
                }

//上面的模板emmm
                     
int main()
{std::ios::sync_with_stdio(false);
int m,n,z,Fs,Ds;
    int F[maxn],D;
    cin>>m>>n>>z;
    for(int i=1;i<=m;i++)
    {cin>>Fs>>Ds;
        for(int j=1;j<=Fs;j++)
            cin>>F[j];
            for(int j=1;j<=Ds;j++)
            {cin>>D;
                for(int k=1;k<=Fs;k++)
                if(!GG[F[k]][100+D])    
                AddEdge(F[k],100+D);//超源点接食物。    
            }
    }//没有牛竟然能过!!!
    for(int i=1;i<=n;i++)
        AddEdge(0,i);
        for(int i=1;i<=z;i++)
            AddEdge(i+100,201);//超汇点接饮料;
cout<<Maxflow(0,201)<<endl;
return 0;
}

 

猜你喜欢

转载自blog.csdn.net/Wyt_code/article/details/81545029