您的位置:首页 > 理论基础 > 计算机网络

hdu 3189(网络流+二分枚举)

2016-06-03 19:23 148 查看
Steady Cow Assignment

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 6422Accepted: 2202
Description

Farmer John's N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns which, of course, have limited capacity. Some cows really like their current barn, and some are not so happy.

FJ would like to rearrange the cows such that the cows are as
equally happy as possible, even if that means all the cows hate their
assigned barn.

Each cow gives FJ the order in which she prefers the barns. A cow's
happiness with a particular assignment is her ranking of her barn. Your
job is to find an assignment of cows to barns such that no barn's
capacity is exceeded and the size of the range (i.e., one more than the
positive difference between the the highest-ranked barn chosen and that
lowest-ranked barn chosen) of barn rankings the cows give their assigned
barns is as small as possible.
Input

Line 1: Two space-separated integers, N and B

Lines 2..N+1: Each line contains B space-separated integers which
are exactly 1..B sorted into some order. The first integer on line i+1
is the number of the cow i's top-choice barn, the second integer on that
line is the number of the i'th cow's second-choice barn, and so on.

Line N+2: B space-separated integers, respectively the capacity of
the first barn, then the capacity of the second, and so on. The sum of
these numbers is guaranteed to be at least N.
Output

Line 1: One integer, the size of the minumum range of barn rankings the cows give their assigned barns, including the endpoints.
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

Explanation of the sample:

Each cow can be assigned to her first or second choice: barn 1 gets
cows 1 and 5, barn 2 gets cow 2, barn 3 gets cow 4, and barn 4 gets cows
3 and 6.

这个题看懂题目才是关键啊。。。错了n多次.
题意:有n头牛b个牛栏,每头牛对每个牛栏有一个满意度,每个牛栏有一个容量,输入n,b 然后输入的矩阵(i,j)代表的是第i头牛第j满意的是牛栏是 g[i][j] 。。就是这句话要看懂,然后最大满意度与最小满意度差值最小是多少(注意此处差值 = MAX-MIN+1).
题解:看懂题后就容易了,构图的话就是建立超级源点S,S向每个牛栏建容量为牛栏容量的单向边,每头牛向超级汇点T连一条容量为1的边,然后枚举差值,当差值为刚好让最大流为n的时候就得到了满足条件的最小差值。

#include <stdio.h>
#include <algorithm>
#include <queue>
#include <string.h>
#include <math.h>
#include <iostream>
#include <math.h>
using namespace std;
const int N = 1100;
const int INF = 999999999;
struct Edge{
int v,next;
int w;
}edge[N*N];
struct Cow{
int love[25];
}cow
;
int head
;
int level
;
int graph

,dis

,cap
;
int tot;
void init(){
memset(head,-1,sizeof(head));
tot=0;
}
void addEdge(int u,int v,int w,int &k){
edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des){
queue<int >q;
memset(level,0,sizeof(level));
level[src]=1;
q.push(src);
while(!q.empty()){
int u = q.front();
q.pop();
if(u==des) return 1;
for(int k = head[u];k!=-1;k=edge[k].next){
int v = edge[k].v;
int w = edge[k].w;
if(level[v]==0&&w!=0){
level[v]=level[u]+1;
q.push(v);
}
}
}
return -1;
}
int dfs(int u,int des,int increaseRoad){
if(u==des) return increaseRoad;
int ret=0;
for(int k=head[u];k!=-1;k=edge[k].next){
int v = edge[k].v;
int w = edge[k].w;
if(level[v]==level[u]+1&&w!=0){
int MIN = min(increaseRoad-ret,w);
w = dfs(v,des,MIN);
if(w>0){
edge[k].w -=w;
edge[k^1].w+=w;
ret+=w;
if(ret==increaseRoad) return ret;
}else level[v] = -1;
}
}
return ret;
}
int Dinic(int src,int des){
int ans = 0;
while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
return ans;
}
int n,b,src,des;
int build(int t,int mid){
init();
for(int i=1;i<=b;i++){
addEdge(src,i,cap[i],tot);
}
for(int i=1;i<=n;i++){
addEdge(i+b,des,1,tot);
}
for(int i=t;i<=t+mid-1&&i<=b;i++){
for(int j=1;j<=n;j++){
addEdge(cow[j].love[i],j+b,1,tot);
}
}
return Dinic(src,des);
}
int main(){
scanf("%d%d",&n,&b);
src = 0,des = n+b+1;
for(int i=1;i<=n;i++){
for(int j=1;j<=b;j++){
scanf("%d",&cow[i].love[j]);
}
}
for(int i=1;i<=b;i++) scanf("%d",&cap[i]);
int l =0,r = b;
int ans = b;
while(l<=r){
int mid = (l+r)>>1;  ///差值
bool flag = false;
for(int i=1;i<=b;i++){ ///枚举最小值
if(build(i,mid)==n) {
flag = 1;
break;
}
}
if(flag) {
ans = mid;
r = mid-1;
}else l = mid+1;
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: