CF1253F Cheap Robot
Codeforces,luogu。
如果我们从走的路径长短出发去思考问题会很困难。因为目的是走到终点,求出容量,这一过程中只有行与不行之分。从此出发,对于当前点
那么由于我们要求的是
设当前电量为
当前点
考虑具体化
对于
所以我们就有:
我是建最小生成树并倍增维护路径上的最大权值。
CODE
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k,q;
struct Graph{
int head[100010],etot = 1;
struct node{ int nxt,v; ll w; }edge[800010];
inline void add(int x,int y,ll w){
edge[++etot] = {head[x],y,w};
head[x] = etot;
}
node & operator [](const int i){ return edge[i]; }
}G,T;
struct P{
int v;
ll dis;
bool friend operator <(P a,P b){ return a.dis > b.dis; }
};
ll dis[100010];
bool vis[100010];
void dij(){
memset(dis,0x3f,sizeof dis);
priority_queue<P> q;
q.push({0,dis[0] = 0});
while(!q.empty()){
int x = q.top().v; q.pop();
if(vis[x])continue;
vis[x] = 1;
for(int i = G.head[x],v = G[i].v;i;i = G[i].nxt,v = G[i].v){
if(dis[v] > dis[x] + G[i].w){
dis[v] = dis[x] + G[i].w;
q.push({v,dis[v]});
}
}
}
}
struct Edge{
int u,v; ll w,cap;
bool friend operator <(Edge a,Edge b){ return a.cap < b.cap; }
}e[300010];
struct DSU{
int fa[100010];
void init(int n){ for(int i = 1;i<=n;++i)fa[i] = i; }
int find(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); }
}dsu;
int st[100010][18];
ll f[100010][18];
int dep[100010];
void dfs(int u,int fa){
dep[u] = dep[fa] + 1;
st[u][0] = fa;
for(int i = 1;i<=17;++i)
st[u][i] = st[st[u][i-1]][i-1],
f[u][i] = max(f[u][i-1],f[st[u][i-1]][i-1]);
for(int i = T.head[u],v = T[i].v;i;i = T[i].nxt,v = T[i].v)if(v ^ fa){
f[v][0] = T[i].w;
dfs(v,u);
}
}
ll LCA(int x,int y){
if(dep[y] < dep[x])swap(x,y);
int t = dep[y] - dep[x];
ll res = 0;
for(int i = 17;~i;--i)if(t&(1<<i))res = max(res,f[y][i]),y = st[y][i];
if(x == y)return res;
for(int i = 17;~i;--i)if(st[x][i] ^ st[y][i]){
res = max({res,f[x][i],f[y][i]});
x = st[x][i], y = st[y][i];
}
return max({res,f[x][0],f[y][0]});
}
int main(){
scanf("%d%d%d%d",&n,&m,&k,&q);
for(int i = 1;i<=m;++i)
scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w),G.add(e[i].u,e[i].v,e[i].w),G.add(e[i].v,e[i].u,e[i].w);
for(int i = 1;i<=k;++i)G.add(0,i,0);
dij();
for(int i = 1;i<=m;++i)
e[i].cap = e[i].w + dis[e[i].u] + dis[e[i].v];
sort(e+1,e+m+1);
dsu.init(n);
for(int i = 1;i<=m;++i){
int u = e[i].u, v = e[i].v; ll w = e[i].cap;
if(dsu.find(u) == dsu.find(v))continue;
dsu.fa[dsu.find(u)] = dsu.find(v);
T.add(u,v,w), T.add(v,u,w);
}
dfs(1,0);
int x,y;
while(q--){
scanf("%d%d",&x,&y);
printf("%lld\n",LCA(x,y));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】