题目
Description
Farmer John的N(1<=N<=1000)头奶牛分别居住在农场所拥有的B(1<=B<=20)个牛棚的某一个里。有些奶牛很喜欢她们当前住的牛棚,而另一些则讨厌再在它们现在所在的牛棚呆下去。
FJ在忍受了若干次奶牛的抱怨后,决定为所有奶牛重新安排牛棚,使最不满的那头奶牛与最高兴的奶牛的心情差异最小,即使这会让所有奶牛都更加郁闷。
每头奶牛都把她对各个牛棚的好感度从高到低排序后告诉了FJ。当然,如果一头奶牛被安排到的牛棚在她给出的列表中越靠后,她就会越郁闷。你可以认为奶牛的郁闷指数是她被分配到的牛棚在列表中的位置。奶牛们是斤斤计较的,她们无法容忍别的奶牛在自己喜欢的牛棚里快乐地生活,而自己却呆在一个自己不喜欢的牛棚里。每个牛棚都只能容纳一定数量的奶牛。FJ希望在每个牛棚都没有超出容量限制的前提下,使最郁闷和最高兴的奶牛的郁闷指数的跨度最小。
FJ请你帮他写个程序,来计算这个最小的郁闷指数跨度到底是多少。
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。
第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
Data Constraint
Hint
【样例说明】
每头奶牛都能被安排进她的第一或第二喜欢的牛棚。下面给出一种合理的分配方案:奶牛1和奶牛5住入牛棚1,牛棚2由奶牛2独占,奶牛4住进牛棚3,剩下的奶牛3和奶牛6安排到牛棚4。
每头奶牛都能被安排进她的第一或第二喜欢的牛棚。下面给出一种合理的分配方案:奶牛1和奶牛5住入牛棚1,牛棚2由奶牛2独占,奶牛4住进牛棚3,剩下的奶牛3和奶牛6安排到牛棚4。
分析
二分答案加网络流
我边上加多一个忧郁值,如果我忧郁值大于当前枚举就不能流
代码
1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 const int N=1e3+10; 7 const int B=21; 8 const int inf=2147483647; 9 int s,t,l; 10 int n,b,ans; 11 int cnt=1,mid; 12 int a[10001]; 13 int dis[10001]; 14 int list[110001]; 15 struct node { 16 int u,v,c,w,nx; 17 }g[2*N*B+2*N+2*B]; 18 void add(int u,int v,int w,int c) { 19 g[++cnt]=(node){u,v,c,w,list[u]};list[u]=cnt; 20 g[++cnt]=(node){v,u,0,0,list[v]};list[v]=cnt; 21 } 22 bool bfs() 23 { 24 queue<int> q; 25 while(!q.empty()) q.pop(); 26 memset(dis,0,sizeof(dis)); 27 q.push(s); 28 dis[s]=1; 29 while (!q.empty()) 30 { 31 int x=q.front(); q.pop(); 32 for (int i=list[x];i;i=g[i].nx) 33 { 34 int y=g[i].v; 35 if (g[i].c&&!dis[y]&&(l<=g[i].w&&g[i].w<=l+mid-1||g[i].w==0)) 36 { 37 dis[y]=dis[x]+1; 38 if (y==t) return 1; 39 q.push(y); 40 } 41 } 42 } 43 return 0; 44 } 45 int dfs(int x,int maxf) 46 { 47 if (x==t) return maxf; 48 int ret=0; 49 for (int i=list[x];i;i=g[i].nx) 50 { 51 int y=g[i].v; 52 if (g[i].c&&dis[y]==dis[x]+1&&(l<=g[i].w&&g[i].w<=l+mid-1||g[i].w==0)) 53 { 54 int f=dfs(y,min(g[i].c,maxf-ret)); 55 if (!f) dis[y]=-1; 56 g[i].c-=f; 57 g[i^1].c+=f; 58 ret+=f; 59 if (ret==maxf) return ret; 60 } 61 } 62 return ret; 63 } 64 bool dinic() 65 { 66 int flow; 67 for (l=1;l<=max(1,b-mid+1);l++) 68 { 69 flow=0; 70 while (bfs()) 71 flow+=dfs(s,inf); 72 for (int i=2;i<=cnt;i+=2) 73 if (g[i].u==s) g[i].c=a[g[i].v],g[i^1].c=0; 74 else g[i].c=1,g[i^1].c=0; 75 if (flow==n) return 1; 76 } 77 return 0; 78 } 79 int main () 80 { 81 cin>>n>>b; 82 s=0,t=n+b+1; 83 for (int i=1;i<=n;i++) 84 for (int j=1,c;j<=b;j++) 85 { 86 cin>>c; 87 add(c,i+b,j,1); 88 } 89 for (int i=1;i<=b;i++) scanf("%d",&a[i]),add(s,i,0,a[i]); 90 for (int i=1;i<=n;i++) add(i+b,t,0,1); 91 int l=1,r=20; 92 while (l<=r) 93 { 94 mid=l+r>>1; 95 if (dinic()) ans=mid,r=mid-1; 96 else l=mid+1; 97 } 98 cout<<ans; 99 }