题目大意:
有n个城市,有一部分是A国的,有一部分是B国的(小于A国的),A国每个城市都有一枚导弹(只有一枚),炸毁别的城市的时间是到这个城市的距离,请问A国最快要多久可以炸毁B国所有城市
解题思路:
先用Floyed来求出最短路,然后二分枚举答案再用匈牙利算法确认是否可以,即可
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int bg[105],head[105],a[105][105],b[105],c[105],w,sum,l,r,mid,n,m,nm;
bool pd[105];
struct rec
{int to,next;
}f[10005];//每一条路线
bool js(int xx)
{int l=0;for (int i=head[xx];i;i=f[i].next)//连接此点的每一条线if (!pd[f[i].to])//可以抢{l=bg[f[i].to];//之前是谁打的bg[f[i].to]=xx;//代替pd[f[i].to]=true;//不能抢了if ((!l)||(js(l))) return true;//之前没人或抢到了bg[f[i].to]=l;//没法打这个城市就还给之前的}return false;//找不到可以打的
}
bool sj(int now)
{memset(head,0,sizeof(head));//清零memset(bg,0,sizeof(bg));//清零w=0;//清零sum=0;//清零for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)if (a[b[i]][c[j]]<=now)//判断是否少于当前的时间{f[++w].to=j;//下一个点f[w].next=head[i];//下一条线head[i]=w;//这个点的第一条线} for (int i=1;i<=n;i++){memset(pd,false,sizeof(pd));//清零if (js(i)) sum++;//判断是否能打到敌人}return sum==m;//判断是否打完
}
int main()
{scanf("%d",&nm);for (int i=1;i<=nm;i++)for (int j=1;j<=nm;j++)scanf("%d",&a[i][j]);for (int k=1;k<=nm;k++)for (int i=1;i<=nm;i++)for (int j=1;j<=nm;j++)if ((i!=j)&&(j!=k)&&(k!=i)&&(a[i][k]+a[k][j]<a[i][j]))a[i][j]=a[i][k]+a[k][j];//Floyedscanf("%d",&n);for (int i=1;i<=n;i++)scanf("%d",&b[i]);scanf("%d",&m);for (int i=1;i<=m;i++)scanf("%d",&c[i]);l=1;r=10000;while(l<=r){mid=(l+r)/2;//二分答案if (sj(mid)) r=mid-1;else l=mid+1;}printf("%d",l);//输出return 0;
}