zoukankan      html  css  js  c++  java
  • 牛棚安排

    牛棚安排

    (Description)

    Farmer John的N(1<=N<=1000)头奶牛分别居住在农场所拥有的B(1<=B<=20)个牛棚的某一个里。有些奶牛很喜欢她们当前住的牛棚,而另一些则讨厌再在它们现在所在的牛棚呆下去。
    FJ在忍受了若干次奶牛的抱怨后,决定为所有奶牛重新安排牛棚,使最不满的那头奶牛与最高兴的奶牛的心情差异最小,即使这会让所有奶牛都更加郁闷。
    每头奶牛都把她对各个牛棚的好感度从高到低排序后告诉了FJ。当然,如果一头奶牛被安排到的牛棚在她给出的列表中越靠后,她就会越郁闷。你可以认为奶牛的郁闷指数是她被分配到的牛棚在列表中的位置。奶牛们是斤斤计较的,她们无法容忍别的奶牛在自己喜欢的牛棚里快乐地生活,而自己却呆在一个自己不喜欢的牛棚里。每个牛棚都只能容纳一定数量的奶牛。FJ希望在每个牛棚都没有超出容量限制的前提下,使最郁闷和最高兴的奶牛的郁闷指数的跨度最小。
    FJ请你帮他写个程序,来计算这个最小的郁闷指数跨度到底是多少。

    (Input)

    第1行: 包含2个用空格隔开的整数N和B,分别表示牛和牛棚的数量
    第2..N+1行: 每行包含B个用空格隔开的整数,刚好完全包含1..B的整数。第i+1行的第一个整数,表示奶牛i最喜欢的牛棚编号。第二个整数表示奶牛i的列表中排在第二位,也就是她第二喜欢的牛棚。依此类推。
    第N+2行: 包含B个用空格隔开的整数,第i个整数表示牛棚i最多能容纳的奶牛的数目。所有牛棚能容纳奶牛头数的和至少是N。

    (Output)

    第1行: 输出一个整数,表示所有奶牛中最高兴与最郁闷的牛的郁闷指数跨度

    (Sample Input)

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

    (Sample Output)

    2

    思路

    我刚看到这题时,没有头绪,只能打表

    比赛后,看了题解,秒懂!!!

    最大流+二分

    解析

    题目要求使最郁闷和最高兴的奶牛的郁闷指数的跨度最小,我们不妨暴力枚举最高兴的,二分指数的跨度
    做完这些,可以考虑网络流。
    源点: (N) 头牛,建一个超级源点连向每一个源点,流量为 (1) .
    汇点: (B) 个牛棚,建一个超级汇点连向每一个汇点,流量为 牛棚能装下的牛的个数 .
    再把 (N) 头牛连向在最郁闷和最高兴的范围(枚举的)中可以去的牛棚
    最后跑一遍最大流就可以 (AC)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    int tot=1,n,m,a[1005][1005],b[10005],d[10005],q[10005],h[100005],cur[100005];
    
    struct edge{
    	int to,nxt,z;
    }e[500000];
    void add(int x,int y,int z)
    {
    	e[++tot].to=y;
    	e[tot].nxt=h[x];
    	e[tot].z=z;
    	h[x]=tot;
    }
    void build(int x,int y)
    {
    	tot=1;
    	memset(h,0,sizeof(h));
    	for (int i=1;i<=n;i++) add(0,i,1),add(i,0,0);
    	for (int i=1;i<=n;i++)
    		for (int j=x;j<=y;j++)
    			add(i,a[i][j]+n,1),add(a[i][j]+n,i,0);
    	for (int i=1;i<=m;i++) add(n+i,n+n+1,b[i]),add(n+n+1,n+i,0);
    }
    bool bfs(int u)
    {
    	for(int i=0;i<=n+n+n;i++) cur[i]=h[i]; 
    	memset(d,0,sizeof(d));
    	memset(q,0,sizeof(q));
    	int head=0,tail=0;
    	d[u]=1;
    	q[++tail]=u;
    	while (head<tail)
    	{
    		head++;
    		for (int i=h[q[head]];i;i=e[i].nxt)
    		{
    			int v=e[i].to;
    			if (d[v]!=0||e[i].z<=0) continue;
    			d[v]=d[q[head]]+1;
    			q[++tail]=v;
    		}
    	}
    	if (d[n+n+1]>0) return true;
    	else return false;
    }
    int dinic(int u,int mn,int fa)
    {
    	if (u==n+n+1||mn==0) return mn;
    	int sum=0,flow=0;
    	for (int i=cur[u];i;i=e[i].nxt)
    	{
    		cur[u]=i;//本代码加入了当前弧优化
    		int v=e[i].to;
    		if (v==fa||d[v]!=d[u]+1||e[i].z<=0) continue;
    		sum=dinic(v,min(mn,e[i].z),u);
    		if (sum<=0) continue;
    		flow+=sum;
    		mn-=sum;
    		e[i].z-=sum;
    		e[i^1].z+=sum;
    		if (mn<=0) break;
    	}
    	return flow;
    }
    bool opt()
    {
    	int res=0;
    	while (bfs(0)==true)
    		res+=dinic(0,2147483647,0);
    	if (res==n) return true;
    	else return false;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			scanf("%d",&a[i][j]);
    	for (int i=1;i<=m;i++)
    		scanf("%d",&b[i]);
    	int ans=2147483647;
    	for (int i=1;i<=m;i++)
    	{
    		int l=0,r=m-i;
    		while(l<=r)
    		{
    			int mid=(l+r)>>1;
    			build(i,i+mid);
    			if (opt()==true) ans=min(ans,mid+1),r=mid-1;
    			else l=mid+1;
    		}	
    	}	
    	printf("%d
    ",ans);
    } 
    
  • 相关阅读:
    Oracle Flashback Technologies (总)
    Oracle Flashback Technologies
    Oracle Flashback Technologies
    Oracle Flashback Technologies
    Oracle Flashback Technologies
    CDB中plug PDB
    PDB重命名
    Redo丢失场景和处理方法
    mkisofs简单定制linux iso
    zabbix 监控tomcat实例
  • 原文地址:https://www.cnblogs.com/nibabadeboke/p/12114842.html
Copyright © 2011-2022 走看看