题意:
人类有H颗星球,外新人有A颗星球,1颗人类星球只能攻占1颗外星人星球,1颗外星人星球也只能被1颗人类星球攻占。人类星球h在满足如下条件可以攻占外星人星球a:
人类舰队从h星球经一定时间到a星球时人类舰队飞船数量大于等于外星人舰队飞船数量。求人类攻占所有外星人星球的最短时间。
思路:
二分时间t,对每个t,求二分图最大匹配看在t时间内是否攻占所有外星人星球。
代码:
//poj 3343
//sepNINE
#include<iostream>
using namespace std;
const int maxN=256;
int M,v1,v2,t,H,A;
bool vis[maxN];
int link[maxN];
bool g[maxN][maxN];
int n[maxN],m[maxN],a[maxN],b[maxN];
int mat[maxN][maxN];
bool dfs(int x)
{
for(int y=1;y<=v2;++y)
if(g[x][y]&&!vis[y]){
vis[y]=true;
if(link[y]==0||dfs(link[y])){
link[y]=x;
return true;
}
}
return false;
}
void hungary()
{
for(int x=1;x<=v1;++x){
memset(vis,false,sizeof(vis));
if(dfs(x))
++M;
}
return ;
}
bool win()
{
int i,j;
memset(link,0,sizeof(link));
memset(g,false,sizeof(g));
for(i=1;i<=H;++i)
for(j=1;j<=A;++j)
if(mat[i][j]<=t&&n[i]+1LL*m[i]*(t-mat[i][j])>=a[j]+1LL*t*b[j])
g[i][j]=1;
M=0;
v1=H;
v2=A;
hungary();
if(M==A)
return true;
return false;
}
int main()
{
while(scanf("%d%d",&H,&A)==2&&H){
int i,j;
for(i=1;i<=H;++i)
scanf("%d%d",&n[i],&m[i]);
for(i=1;i<=A;++i)
scanf("%d%d",&a[i],&b[i]);
for(i=1;i<=H;++i)
for(j=1;j<=A;++j)
scanf("%d",&mat[i][j]);
int low=0,high=INT_MAX;
while(low<high){
//t=(low+high)/2;
t=low/2+high/2;
if(low%2==1&&high%2==1) ++t;
if(win())
high=t;
else
low=t+1;
}
if(low==INT_MAX)
printf("IMPOSSIBLE\n");
else
printf("%d\n",low);
}
return 0;
}