hihoCoder#1139(二分+bfs)
描述
在上一回和上上回里我们知道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
思路:求所有路径中最短边的最大值。若将所有路径(注意:此时同一个路径和边可能访问多次)遍历一次TLE。
TLE代码:#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN=100005; const int INF=0x3f3f3f3f; struct Edge{ int to,w,net; }es[MAXN]; int n,m,k,ter; int head[MAXN],tot; int vis[MAXN]; int vec[MAXN],top; int res; void addedge(int u,int v,int w) { es[tot].to=v; es[tot].w=w; es[tot].net=head[u]; head[u]=tot++; } void dfs(int dep,int u,int mx) { if(dep>k) return; if(u==ter) { res=min(res,mx); return ; } for(int i=head[u];i!=-1;i=es[i].net) { int v=es[i].to; int w=es[i].w; int mmx=max(mx,w); if(!vis[v]) { vis[v]=1; dfs(dep+1,v,mmx); vis[v]=0; } } } int main() { memset(head,-1,sizeof(head)); scanf("%d%d%d%d",&n,&m,&k,&ter); for(int i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } res=INF; dfs(0,1,0); printf("%d\n",res); return 0; }
若只求一个最大值或者最小值可尝试采用二分方法求解。
#include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXN=100005; const int INF=0x3f3f3f3f; struct Edge{ int to,w,net; }es[MAXN+MAXN]; int head[MAXN],tot; int vis[MAXN]; int step[MAXN]; int n,m,k,ter; void addedge(int u,int v,int w) { es[tot].to=v; es[tot].w=w; es[tot].net=head[u];; head[u]=tot++; } bool bfs(int limit) { memset(step,0,sizeof(step)); memset(vis,0,sizeof(vis)); queue<int> que; que.push(1); vis[1]=1; while(!que.empty()) { int u=que.front();que.pop(); if(u==ter) { return true; } for(int i=head[u];i!=-1;i=es[i].net) { int v=es[i].to; if(!vis[v]&&es[i].w<=limit&&step[u]+1<=k) { step[v]=step[u]+1; vis[v]=1; que.push(v); } } } return false; } int main() { memset(head,-1,sizeof(head)); scanf("%d%d%d%d",&n,&m,&k,&ter); for(int i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } int l=0,r=INF; while(r-l>1) { int mid=(l+r)>>1; if(bfs(mid)) { r=mid; } else { l=mid; } } printf("%d\n",r); return 0; }
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 2025成都.NET开发者Connect圆满结束
· 后端思维之高并发处理方案
· 在 VS Code 中,一键安装 MCP Server!
· 千万级大表的优化技巧
· langchain0.3教程:从0到1打造一个智能聊天机器人
2015-08-02 HDOJ1073(gets 应用)
2015-08-02 HDOJ(1069)最长下降子序列