cf-ronnd-600-F-Cheap Robot

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電池容量的最小值。
dud_u是u點到距離u點最近的充電站的距離。
到達u點時,剩餘容量爲x。
如果x<dux<d_u,則u點不能到達任意的前k個點。
否則,x>=dux>=d_u,u點是從某個充電站過來,所以x<=Cdux<=C-d_u,因此,從u點到最近的點,再回來,能使x增大,所以,到達某點剩餘的電量爲CduC-d_u
如果u能到達v,則(Cdu)wi>=dv(C-d_u)-w_i>=d_v即:c>=du+dv+wic>=d_u+d_v+w_i
du+dv+wid_u+d_v+w_i視爲點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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章