题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2413
思路:由于要求最少的时间,可以考虑二分,然后就是满足在limit时间下,如果地球战舰数目比外星战舰数目多,就连边,然后求最大匹配即可,判断匹配数目是否等于外星球数目,如果相等,说明可以占领,继续二分。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define MAXN 333 8 #define inf 1<<20 9 typedef long long ll; 10 vector<int>map[MAXN]; 11 int mark[MAXN]; 12 int ly[MAXN]; 13 int hp[MAXN],hq[MAXN]; 14 int ap[MAXN],aq[MAXN]; 15 int tt[MAXN][MAXN]; 16 int n,m; 17 18 int dfs(int u) 19 { 20 for(int i=0;i<map[u].size();i++){ 21 int v=map[u][i]; 22 if(!mark[v]){ 23 mark[v]=true; 24 if(ly[v]==-1||dfs(ly[v])){ 25 ly[v]=u; 26 return 1; 27 } 28 } 29 } 30 return 0; 31 } 32 33 bool MaxMatch(int limit) 34 { 35 for(int i=1;i<=n;i++)map[i].clear(); 36 for(int i=1;i<=n;i++){ 37 for(int j=1;j<=m;j++){ 38 ll t1=1ll+hp[i]+(ll)(limit-tt[i][j])*hq[i]; 39 ll t2=1ll+ap[j]+(ll)limit*aq[j]; 40 if(t1>=t2)map[i].push_back(j); 41 } 42 } 43 int res=0; 44 memset(ly,-1,sizeof(ly)); 45 for(int i=1;i<=n;i++){ 46 memset(mark,false,sizeof(mark)); 47 res+=dfs(i); 48 } 49 if(res==m)return true; 50 return false; 51 } 52 53 int main() 54 { 55 // freopen("1.txt","r",stdin); 56 while(scanf("%d%d",&n,&m),(n+m)){ 57 for(int i=1;i<=n;i++) 58 scanf("%d%d",&hp[i],&hq[i]); 59 for(int i=1;i<=m;i++) 60 scanf("%d%d",&ap[i],&aq[i]); 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=m;j++) 63 scanf("%d",&tt[i][j]); 64 int low=0,high=inf,mid,ans=inf; 65 while(low<=high){ 66 mid=(low+high)>>1; 67 if(MaxMatch(mid)){ 68 ans=mid; 69 high=mid-1; 70 }else 71 low=mid+1; 72 } 73 if(ans<inf){ 74 printf("%d ",ans); 75 }else 76 puts("IMPOSSIBLE"); 77 } 78 return 0; 79 }