hihocoder hiho第38周: 二分·二分答案 (二分搜索算法应用:二分搜索值+bfs判断可行性 )
题目1 : 二分·二分答案
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
在上一回和上上回里我们知道Nettle在玩《艦これ》,Nettle在整理好舰队之后终于准备出海捞船和敌军交战了。
在这个游戏里面,海域是N个战略点(编号1..N)组成,如下图所示
其中红色的点表示有敌人驻扎,猫头像的的点表示该地图敌军主力舰队(boss)的驻扎点,虚线表示各个战略点之间的航线(无向边)。
在游戏中要从一个战略点到相邻战略点需要满足一定的条件,即需要舰队的索敌值大于等于这两点之间航线的索敌值需求。
由于提高索敌值需要将攻击机、轰炸机换成侦察机,舰队索敌值越高,也就意味着舰队的战力越低。
另外在每一个战略点会发生一次战斗,需要消耗1/K的燃料和子弹。必须在燃料和子弹未用完的情况下进入boss点才能与boss进行战斗,所以舰队最多只能走过K条航路。
现在Nettle想要以最高的战力来进攻boss点,所以他希望能够找出一条从起始点(编号为1的点)到boss点的航路,使得舰队需要达到的索敌值最低,并且有剩余的燃料和子弹。
特别说明:两个战略点之间可能不止一条航线,两个相邻战略点之间可能不止一条航线。保证至少存在一条路径能在燃料子弹用完前到达boss点。
输入
第1行:4个整数N,M,K,T。N表示战略点数量,M表示航线数量,K表示最多能经过的航路,T表示boss点编号, 1≤N,K≤10,000, N≤M≤100,000
第2..M+1行:3个整数u,v,w,表示战略点u,v之间存在航路,w表示该航路需求的索敌值,1≤w≤1,000,000。
输出
第1行:一个整数,表示舰队需要的最小索敌值。
- 样例输入
-
5 6 2 5 1 2 3 1 3 2 1 4 4 2 5 2 3 5 5 4 5 3
- 样例输出
-
3
代码:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#define N 10000+10
using
namespace
std;
struct
node
{
int
v;
int
w;
};
int
n, m, kk, boss;
vector<node>q[100000+10];
bool
bfs(
int
k)
{
//起点编号为1
int
fa[N];
memset
(fa, 0,
sizeof
(fa));
fa[1]=kk;
bool
vis[N];
memset
(vis,
false
,
sizeof
(vis));
queue<
int
>p;
p.push(1); vis[1]=
true
;
while
(!p.empty())
{
int
cur=p.front(); p.pop();
for
(
int
i=0; i<q[cur].size(); i++)
{
int
dd=q[cur][i].v;
int
ff=q[cur][i].w;
if
(vis[dd]==
false
&&ff<=k )
{
vis[dd]=
true
;
fa[dd]=fa[cur]-1;
if
(dd==boss && fa[dd]>=0 )
{
return
true
;
}
p.push(dd);
}
}
}
return
false
;
}
int
main()
{
scanf
(
"%d %d %d %d"
, &n, &m, &kk, &boss);
int
i, j, k;
int
u, v, w;
node t;
int
ma=-1, mi=21000000000;
for
(i=0; i<m; i++)
{
scanf
(
"%d %d %d"
, &u, &v, &w);
ma=max(ma, w); mi=min(mi, w);
t.v=v; t.w=w;
q[u].push_back(t);
t.v=u; t.w=w;
q[v].push_back(t);
//
}
//二分枚举最大和最小之间的区间
i=mi; j=ma;
int
mid;
int
pos;
while
(i<=j)
{
mid=(i+j)/2;
if
(bfs(mid)==
true
)
{
if
(bfs(mid-1)==
false
)
{
pos = mid;
break
;
}
else
j=mid;
}
else
i=mid;
}
printf
(
"%d\n"
, pos);
return
0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步