[匈牙利][Floyd] Jzoj P1015 导弹
题解
- 对于这题来说,直接求摧毁时间应该是不可信的,那么考虑二分出一个答案,问题就转换为判断性的了
- 显然导弹的飞行时间应该是要最短,这样的话才能建设一套完美的防御系统
- 那么就可以用Floyd处理出两两城市之间的最短路(k<=100)
- 因为这题要求的其实就是最大匹配,然后在最大匹配里判断飞行是否超过二分出的mid
- 一套防御系统要不全档下,漏掉一个也会挂菜,所有要全部档下才算是一个成功的防御系统
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define N 210 5 using namespace std; 6 int a[N][N],p[N],q[N],bz[N],vis[N],i,n,mid,num1,num2,ans=0; 7 bool xyl(int x) 8 { 9 if (bz[x]==i) return 0; 10 bz[x]=i; 11 for (int i=1;i<=num1;i++) 12 if (a[q[x]][p[i]]<=mid) 13 if (!vis[i]||xyl(vis[i])) 14 { vis[i]=x; return 1; } 15 return 0; 16 } 17 bool check() 18 { 19 memset(bz,0,sizeof(bz)),memset(vis,0,sizeof(vis)),ans=0; 20 for (i=1;i<=num2;i++) if (xyl(i)) ans++; else return 0; 21 if (ans==num2) return 1; else return 0; 22 } 23 int main() 24 { 25 scanf("%d",&n); 26 for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%d",&a[i][j]); 27 for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]=min(a[i][j],a[i][k]+a[k][j]); 28 scanf("%d",&num1); for (int i=1;i<=num1;i++) scanf("%d",&p[i]); 29 scanf("%d",&num2); for (int i=1;i<=num2;i++) scanf("%d",&q[i]); 30 int l=1,r=100; 31 while (l+1<r) 32 { 33 mid=l+r>>1; 34 if (check()) r=mid; else l=mid; 35 } 36 mid=l; if (check()) r=l; 37 printf("%d",r); 38 }