Steady Cow Assignment POJ - 3189
题意:
有b个牛舍,n头牛。
每头牛对牛舍的喜爱程度不同。
问:
怎样分配可以使得牛的喜爱程度之差最小。
思路:
- 二分差值,之后枚举下界(牛舍只有20)
- 之后建图,跑最大匹配。
AC
#include <iostream>
#include <map>
#include <string>
#include <cstring>
#include <cstdio>
#define mst(x,a) memset(x,a,sizeof(x))
#define fzhead EDGE(int _v, int _next)
#define fzbody to(_v), next(_next)
using namespace std;
const int maxn=1e3+100;
const int maxm=2e5+10;
const int inf=0x3f3f3f3f;
struct node{
int cnt,k[maxn];//cnt:右独立集匹配的个数, k右独立集,匹配点的集合
}link[maxn];
struct EDGE{
int to,next;
EDGE(){}
fzhead:fzbody{}
}e[maxm];
int head[maxn],cnt,mx[maxn];
void add(int bg, int to){
e[++cnt]=EDGE(to, head[bg]);
head[bg]=cnt;
}
int n,b ,vis[maxn];
int ma[maxn][30];
bool used[maxn];
bool dfs(int u)
{
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v=e[i].to;
if(!used[v])
{
used[v] = 1;
if(link[v].cnt<mx[v]){///
link[v].k[link[v].cnt++]=u;
return 1;
}///
for(int j=0; j<link[v].cnt; j++)
if(dfs(link[v].k[j]))
{
link[v].k[j]=u;
return 1;
}
}
}
return 0;
}
bool check(int x,int y)//max_match()
{
cnt=0;
mst(head,-1);mst(used,0);mst(link,0);
mst(vis,0);
int ans = 0;
for(int i=1; i<=n; i++){
for(int j=x;j<=min(y,b); j++){
add(i,ma[i][j]+n);
// cout<<"(i,j)-> "<<j<<' '<<i<<' ';
}
}
// cout<<endl;
for(int i = 1;i <=n;++i)//if(!vis[i])
{
mst(used,0);
if(!dfs(i))return false;
///TLE if(!vis[i])ans += dfs(i);//最大匹配
}
return true;
/// TLE return ans==n;
}
void work(){
for(int i=1; i<=n; i++){
for(int j=1; j<=b; j++)scanf("%d", ma[i]+j);
}
for(int i=1; i<=n+b; i++)mx[i]=1;
for(int j=1; j<=b; j++)scanf("%d",mx+j+n);
int l=1,r=b,ans=0;
while(l<=r){
int mid=(l+r)>>1;
int flag=0;
for(int i=1; i<=b; i++){
if(check(i,mid+i-1)){
flag=1;
break;
}
}
if(flag) r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans<<endl;
}
int main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
while(cin>>n>>b){
work();
}
return 0;
}