版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/ssllyf/article/details/86635968
导弹
题目大意:
有n个城市,有一部分是A国的,有一部分是B国的(小于A国的),A国每个城市都有一枚导弹(只有一枚),炸毁别的城市的时间是到这个城市的距离,请问A国最快要多久可以炸毁B国所有城市
样例输入
3
0 2 1
2 0 10
1 10 0
1
2
1
3
样例输出
3
数据范围限制
各城市距离<=100
城市数<=100
解题思路:
先用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()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
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];//Floyed
scanf("%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);//输出
fclose(stdin);
fclose(stdout);
return 0;
}