地球和外星球大战,地球有n个飞船,外星球有m个飞船,每个飞船有自己的其实战舰和战舰增长率,星球于星球之间有距离,问你最少多少年地球可以打败外星球,每个星球最多只能和一个星球对战...
思路:
题意的最后一句话告诉我们这个题目满足二分图,我们可以二分枚举多少年打败,每次都重新建图,对于H[i] , 和 A[j],如果当前二分:
(mid - map[i][j]) * H[i].p + H[i].st >= A[i].p * mid + A[i].st ,(地球攻击外星球,所以跑路的时间是地球付出) 就建边i,j,然后二分匹配,如果得到的匹陪数是外星战舰数,那么满足,则 up = mid - 1.........
#include<stdio.h> #include<string.h> #define N_node 250 + 100 #define N_edge 250 * 250 + 1000 #define INF 2000000000 typedef struct { int to ,next; }STAR; typedef struct { __int64 st ,p; }NODE; NODE H[N_node] ,A[N_node]; STAR E[N_edge]; __int64 map[N_node][N_node]; int mk_gx[N_node] ,mk_dfs[N_node]; int list[N_node] ,tot; void add(int a ,int b) { E[++tot].to = b; E[tot].next = list[a]; list[a] = tot; } int DFS_XYL(int s) { for(int k = list[s] ;k ;k = E[k].next) { int to = E[k].to; if(mk_dfs[to]) continue; mk_dfs[to] = 1; if(mk_gx[to] == -1 || DFS_XYL(mk_gx[to])) { mk_gx[to] = s; return 1; } } return 0; } void Buid(__int64 mid ,int n ,int m) { memset(list ,0 ,sizeof(list)); tot = 1; for(int i = 1 ;i <= n ;i ++) for(int j = 1 ;j <= m ;j ++) { __int64 h = (mid - map[i][j]) * H[i].p + H[i].st; __int64 a = mid * A[j].p + A[j].st; if(h >= a) add(i ,j); } } bool OK(int n ,int m) { int sum = 0; memset(mk_gx ,255 ,sizeof(mk_gx)); for(int i = 1 ;i <= n ;i ++) { memset(mk_dfs ,0 ,sizeof(mk_dfs)); sum += DFS_XYL(i); } return sum == m; } int main () { int i ,j ,n ,m; while(~scanf("%d %d" ,&n ,&m) && n + m) { for(i = 1 ;i <= n ;i ++) scanf("%I64d %I64d" ,&H[i].st ,&H[i].p); for(i = 1 ;i <= m ;i ++) scanf("%I64d %I64d" ,&A[i].st ,&A[i].p); for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= m ;j ++) scanf("%I64d" ,&map[i][j]); if(n < m) { printf("IMPOSSIBLE "); continue; } __int64 low ,mid ,up; low = 0; up = INF; int ans = -1; while(low <= up) { mid = (low + up) >> 1; Buid(mid ,n ,m); if(OK(n ,m)) { up = mid - 1; ans = mid; } else low = mid + 1; } if(ans == -1) printf("IMPOSSIBLE "); else printf("%d " ,ans); } return 0; }