• 奶牛食品


    奶牛食品

    Time Limit:10000MS  Memory Limit:65536K
    Total Submit:132 Accepted:61 
    Case Time Limit:1000MS

    Description

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

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

    每一种食物和饮料仅仅能由一头牛来用。

    比如假设食物2被一头牛吃掉了,没有别的牛能吃到食物2。 

    Input

    第一行包括三个用空格分开的整数N,F和D; 

    接下来的N行描写叙述每一个奶牛的信息: 
    第i+1行的前两个整数为F_i和D_i,接下来的F_i个整数表示奶牛i喜欢的食品编号。再接下来的D_i个整数表示奶牛i喜欢的饮料编号。 

    Output

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

    Sample Input

    4 3 3
    2 2 1 2 3 1
    2 2 2 3 1 2
    2 2 1 3 1 2
    2 1 1 3 3 

    Sample Output

    3
    
    

    Hint

    输入数据表明:奶牛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和饮料4。 

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

    Source

    网络流 usaco open 2007 gold dining


    建图。左边是食物,中间是牛。右边是饮料,这样仅仅拆n个点(代表牛的点),图中每一条边的容量都为1。

    如图:

    示意图























    为什么食物和牛不用拆点呢?

    我想拆点仅仅在下面这样的情况下才须要(出度和入度都大于1)









    #include<cstdio>
    using namespace std;
    #define inf 2100000000
    #define maxe 50000
    #define maxv 500
    int et;
    int n, f, d;
    int opp[maxe], len[maxe], end[maxe], last[maxv], next[maxe];
    int dis[maxv], vd[maxv];
    int Min(int a, int b)
    {
    	return a<b?a:b;
    }
    int vt;
    int dfs(int u, int flow)
    {
    	int temp, delta, i, e;
    	if(u==vt)	return flow;
    	delta=0;
    	for(i=last[u]; i; i=next[i])
    	{
    		e=end[i];
    		if(len[i]>0&&dis[u]==dis[e]+1)
    		{
    			temp=dfs(e, Min(flow-delta, len[i]));
    			len[i]-=temp;
    			len[opp[i]]+=temp;
    			delta+=temp;
    			if(delta==flow||dis[1]>=vt)return delta;
    		}
    	}
    	if(dis[1]>=vt)return delta;
    	vd[dis[u]]--;
    	if(vd[dis[u]]==0)dis[1]=vt;
    	dis[u]++;
    	vd[dis[u]]++;
    	return delta;
    }
    void adde(int s, int e, int c)
    {
    	et++;
    	len[et]=c;
    	end[et]=e;
    	next[et]=last[s];
    	last[s]=et;
    }
    void addde(int s, int e, int c)
    {
    	adde(s, e, c);
    	opp[et]=et+1;
    	adde(e, s, 0);
    	opp[et]=et-1;
    }
    int main()
    {
    	int ans=0;
    	int i, j, k, fi, di, t;
    	scanf("%d%d%d", &n, &f, &d);
    	vt=2+f+n*2+d;
    	for(i=1; i<=f; i++)
    	{
    		addde(1, 1+i, 1);
    	}
    	for(i=1; i<=n; i++)
    	{
    		scanf("%d%d", &fi, &di);
    		for(j=1; j<=fi; j++)
    		{
    			scanf("%d", &t);
    			addde(1+t, 1+f+i, 1);
    		}
    		for(j=1; j<=di; j++)
    		{
    			scanf("%d", &t);
    			addde(1+f+n+i, 1+f+n*2+t, 1);
    		}
    	}
    	for(i=1; i<=n; i++)	addde(1+f+i, 1+f+n+i, 1);
    	for(i=1; i<=d; i++)	addde(1+f+n+n+i, vt, 1);
    	while(dis[1]<vt)	ans+=dfs(1, inf);
    	printf("%d", ans);
    	return 0;
    }


  • 相关阅读:
    XML基础
    vue项目使用WebViewJavascriptBridge
    vue cli3 打包部署 Failed to load resource: net::ERR_FILE_NOT_FO 找不到路径问题
    js 将一个数组插入到另一个数组的方法
    div随意拖动小例子
    带转义符的json解释
    银行卡四位数空隔
    收录-获取时间、日期
    封装的一些例子
    easyui-validatebox 验证
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6916300.html
Copyright © 2020-2023  润新知