Cheap Robot
You’re given a simple, undirected, connected, weighted graph with n nodes and m edges.
Nodes are numbered from 1 to n. There are exactly k centrals (recharge points), which are nodes 1,2,…,k.
We consider a robot moving into this graph, with a battery of capacity c, not fixed by the constructor yet. At any time, the battery contains an integer amount x of energy between 0 and c inclusive.
Traversing an edge of weight wi is possible only if x≥wi, and costs wi energy points (x:=x−wi).
Moreover, when the robot reaches a central, its battery is entirely recharged (x:=c).
You’re given q independent missions, the i-th mission requires to move the robot from central ai to central bi.
For each mission, you should tell the minimum capacity required to acheive it.
Input
The first line contains four integers n, m, k and q (2≤k≤n≤105 and 1≤m,q≤3⋅105).
The i-th of the next m lines contains three integers ui, vi and wi (1≤ui,vi≤n, ui≠vi, 1≤wi≤109), that mean that there’s an edge between nodes u and v, with a weight wi.
It is guaranteed that the given graph is simple (there is no self-loop, and there is at most one edge between every pair of nodes) and connected.
The i-th of the next q lines contains two integers ai and bi (1≤ai,bi≤k, ai≠bi).
Output
You have to output q lines, where the i-th line contains a single integer : the minimum capacity required to acheive the i-th mission.
Examples
input
10 9 3 1
10 9 11
9 2 37
2 4 4
4 1 8
1 5 2
5 7 3
7 3 2
3 8 4
8 6 13
2 3
output
12
input
9 11 3 2
1 3 99
1 4 5
4 5 3
5 6 3
6 4 11
6 7 21
7 2 6
7 8 4
8 9 3
9 2 57
9 3 2
3 1
2 3
output
38
15
給定一個聯通、無向、無環圖,前k個點可以充電,經過一條邊花費w電,q個詢問,從前k個點中選取兩個點a,b。求a到b電池容量的最小值。
設是u點到距離u點最近的充電站的距離。
到達u點時,剩餘容量爲x。
如果,則u點不能到達任意的前k個點。
否則,,u點是從某個充電站過來,所以,因此,從u點到最近的點,再回來,能使x增大,所以,到達某點剩餘的電量爲
如果u能到達v,則即:
將視爲點u,v之間的邊權。
求兩點之間路徑上最大值的最小值。
樹剖或者重構樹都能做。
#include<bits/stdc++.h>
using namespace std;
char buf[1<<20],*P1=buf,*P2=buf;
#define gc() (P1==P2&&(P2=(P1=buf)+fread(buf,1,1<<20,stdin),P1==P2)?EOF:*P1++)
#define TT template<class T>inline
TT bool read(T &x){
x=0;char c=gc();bool f=0;
while(c<48||c>57){if(c==EOF)return 0;f^=(c=='-'),c=gc();}
while(47<c&&c<58)x=(x<<3)+(x<<1)+(c^48),c=gc();
if(f)x=-x;return 1;
}
TT bool read(T&a,T&b){return read(a)&&read(b);}
TT bool read(T&a,T&b,T&c){return read(a)&&read(b)&&read(c);}
typedef long long ll;
const ll MAXN=1e5+8,mod=1e9+8,inf=1ll<<50;
#define lowbit(x) (x&(-x))
struct E{
int x,y,nt;ll v;
bool operator<(const E&b)const{return v<b.v;}
}e[MAXN*6];
int head[MAXN],cnt;
inline void add(int x,int y,ll v){
e[++cnt].nt=head[x];head[x]=cnt;
e[cnt].v=v;e[cnt].x=x;e[cnt].y=y;
}
struct Node{int y,nt;}node[MAXN<<1];
int Nodehead[MAXN<<1],Nodecnt;
inline void addNode(int x,int y){
node[++Nodecnt].nt=Nodehead[x];
node[Nodecnt].y=y;
Nodehead[x]=Nodecnt;
}
int n,m,k,q;
ll dis[MAXN];
void dijkstra(){
priority_queue<pair<ll,int>>que;
for(int i=1;i<=k;++i)que.emplace(0,i);
for(int i=k+1;i<=n;++i)dis[i]=inf;
int x,y;ll v;
while(!que.empty()){
x=que.top().second;
v=-que.top().first;
que.pop();
if(dis[x]!=v)continue;
for(int i=head[x];i;i=e[i].nt){
y=e[i].y,v=e[i].v;
if(dis[y]>dis[x]+v){
dis[y]=dis[x]+v;
que.emplace(-dis[y],y);
}
}
}
}
int deep[MAXN<<1],son[MAXN<<1],fa[MAXN<<1],tot[MAXN<<1];
void dfs1(int x,int f){
deep[x]=deep[f]+1,tot[x]=1,fa[x]=f;
int max_son=-1;
for(int i=Nodehead[x];i;i=node[i].nt){
int y=node[i].y;
if(tot[y])continue;
dfs1(y,x);
tot[x]+=tot[y];
if(max_son<tot[y])
son[x]=y,max_son=tot[y];
}
}
int top[MAXN<<1];
void dfs2(int x,int tp){
top[x]=tp;
if(son[x])dfs2(son[x],tp);
else return;
for(int i=Nodehead[x];i;i=node[i].nt){
int y=node[i].y;
if(top[y])continue;
dfs2(y,y);
}
}
int lca(int x,int y){
while(top[x]^top[y]){
if(deep[top[x]]<deep[top[y]])y=fa[top[y]];
else x=fa[top[x]];
}
if(deep[x]>deep[y])return y;
return x;
}
int find(int x){return x^fa[x]?(fa[x]=find(fa[x])):x;}
ll val[MAXN<<1];
void kruskal(){
int id=n;
sort(e+1,e+1+cnt);
for(int i=0;i<n*2+2;++i)fa[i]=i;
for(int i=1;i<=cnt;++i){
int fx=find(e[i].x),fy=find(e[i].y);
if(fx^fy){
val[++id]=e[i].v;
fa[fx]=fa[fy]=id;
addNode(id,fx);
addNode(id,fy);
}
}
dfs1(id,0);
dfs2(id,id);
}
int main() {
read(n,m),read(k,q);
for(int i=0;i<m;++i){
int x,y;ll v;
read(x,y);read(v);
add(x,y,v);
add(y,x,v);
}
dijkstra();
for(int i=1;i<=n;++i)
for(int j=head[i];j;j=e[j].nt)
e[j].v+=dis[e[j].x]+dis[e[j].y];
kruskal();
while(q--){
int x,y;
read(x,y);
printf("%I64d\n",val[lca(x,y)]);
}
return 0;
}