稳定的奶牛分配
Time Limit:10000MS Memory Limit:65536K
Total Submit:53 Accepted:23
Case Time Limit:1000MS
Description
农夫约翰有N(1<=N<=1000)只奶牛,每只奶牛住在B(1<=B<=20)个奶牛棚中的一个。当然,奶牛棚的容量有限。有些奶牛对它现在住的奶牛棚很满意,有些就不太满意了。
农夫约翰想要重新安排这些奶牛,使得奶牛的满意度尽可能相同,尽管有可能这意味者所有的奶牛都不喜欢新分配的奶牛棚。
每只奶牛都按顺序给出她喜欢的奶牛棚。在某个分配方案中,一只奶牛的满意度等于她对她的奶牛棚的评价等级。你的工作是找出一种分配方案使得没有奶牛棚超出它的容量,而且奶牛给分配到的奶牛棚的评价等级的相对范围(即分配到的等级最高的奶牛棚和等级最低的奶牛棚之间的差值)尽可能的小。
Input
第1行:两个用空格隔开的整数,N和B
第2..N+1行:每一行都有B个用空格隔开的正整数,它们恰好是1到B的一个排列。第i+1行的第一个整数是第i只奶牛的首选牛棚的编号,该行的第二个整数是第i只奶牛的第二选择,等等。
第N+2行:B个用空格隔开的整数,分别表示这B个奶牛棚的容量。这些数的和保证至少为N。
Output
一个整数,被分配到的牛棚等级的最小相对差值,输出得到该相对差时所包含的不同等级的牛棚个数。
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
Hint
每个奶牛都被安排在它的第一选择或第二选择:1号牛棚安排1号奶牛和5号奶牛,2号牛棚安排2号奶牛,3号牛棚安排4号奶牛,4号牛棚安排3号奶牛和6号奶牛。
输出样例
表示得到最小相对差为1,这时奶牛们入住进了两种不同等级的牛棚
Source
网络流 usaco feb06 gold
这道题我们很容易就能想到构图的方法:
源点连接每一个奶牛,权值为1,每一个奶牛连接每一个牛棚,权值为1,牛棚连接汇点,权值为牛棚容量。
那么我们怎么得到答案呢?
首先先枚举答案(这里可以用二分也可以直接循环枚举),然后再枚举牛棚的最高等级(我们设1为最高等级)
最后对于每一个枚举的对象跑一次SAP就可以了
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int inf=1e9,maxn=2005;
int n,b,op,ed,M=2,p[maxn],cow[maxn][maxn],g[maxn][maxn];
int dis[maxn],vd[maxn];
void _read(int &xx){
char tt=getchar();
while(tt>'9'||tt<'0')tt=getchar();
for(xx=0;tt>='0'&&tt<='9';tt=getchar())xx=xx*10+(tt-'0');
}
int dfs(int u,int flow){
if(u==ed)return flow;
int v,temp,delta=0;
for(v=1;v<=ed;v++)
if(g[u][v]&&dis[u]==dis[v]+1){
temp=dfs(v,min(flow-delta,g[u][v]));
g[u][v]-=temp;
g[v][u]+=temp;
delta+=temp;
if(delta==flow||dis[op]>=ed)return delta;
}
if(dis[op]>=ed)return delta;
vd[dis[u]]--;
if(vd[dis[u]]==0)dis[op]=ed;
dis[u]++;
vd[dis[u]]++;
return delta;
}
int main(){
int i,j,k,ans;
scanf("%d%d",&n,&b);
op=n+b+1,ed=op+1;
for(i=1;i<=n;i++)
for(j=1;j<=b;j++)
_read(cow[i][j]);
for(i=1;i<=b;i++)_read(p[i]);
for(ans=0;ans<b;ans++)
for(k=1;k+ans<=b;k++){
int t=0;
memset(g,0,sizeof(g));
memset(dis,0,sizeof(dis));
for(i=1;i<=n;i++)g[op][i]++;
for(i=1;i<=b;i++)g[i+n][ed]+=p[i];
for(i=1;i<=n;i++)
for(j=k;j<=k+ans;j++)
g[i][cow[i][j]+n]++;
while(dis[op]<ed)t+=dfs(op,inf);
if(t==n){
cout<<ans+1;
return 0;
}
}
}