[NOI2018] 归程 题解
注意到题解区的解释好像都不清楚,错译我来写一篇。
首先建重构树,然后一个子树内的节点(根节点权值 \(\le p\))的点都可以到达。
答案就是这些点到点 \(1\) 的最短路的最小值。题解都没解释这是为什么。
注意到重构树的子树在原图上相当于一张导出子图,我们定义这张子图边上的点(即和不在这张子图内的点有连边)为特殊点,其他点离开子图都需要经过特殊点,所以答案即为特殊点的最短路最小值。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int dis[400005] , f[400005] , len , n , m , fa[400005][31] , road[400005] , lastans , Q , k , maxhigh;
bool vis[400005];
struct tree{
int val , fa , ls , rs;
}dots[400005];
struct edge{
int to , nxt , val , high;
}ed[800005];
struct Edge{
int u , v , w;
bool operator < (const Edge &B)const{
return w > B.w;
}
}e[800005];
int head[400005] , edgecnt;
void add_edge(int u , int v , int w , int a){
edgecnt++ , ed[edgecnt].to = v , ed[edgecnt].val = w , ed[edgecnt].high = a , ed[edgecnt].nxt = head[u];
head[u] = edgecnt;
}
priority_queue<pair<int,int> > q;
void dijkstra(int s){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[s] = 0;
q.push({0,s});
while(!q.empty()){
pair<int,int> p = q.top();q.pop();
int u = p.second;
if(vis[u])continue;
vis[u] = 1;
for(int i=head[u];i;i=ed[i].nxt){
int v = ed[i].to;
if(dis[v]>dis[u]+ed[i].val){
dis[v] = dis[u] + ed[i].val;
if(!vis[v])q.push({-dis[v],v});
}
}
}
}
int find(int x){
if(f[x]==x)return x;
return f[x] = find(f[x]);
}
void kruskal(){
len = n;
sort(e+1,e+m+1);
for(int i=1;i<=2*n;i++)f[i] = i , dots[i] = {0,0,0,0};
for(int i=1;i<=m;i++){
int u = find(e[i].u) , v = find(e[i].v) , w = e[i].w;
if(u==v)continue;
dots[++len] = {w,0,u,v};
dots[u].fa = len , dots[v].fa = len;
f[u] = len , f[v] = len;
}
}
void dfs(int u){
fa[u][0] = dots[u].fa , road[u] = dis[u];
for(int j=1;j<30;j++)fa[u][j] = fa[fa[u][j-1]][j-1];
if(dots[u].ls)dfs(dots[u].ls) , road[u] = min(road[u],road[dots[u].ls]);
if(dots[u].rs)dfs(dots[u].rs) , road[u] = min(road[u],road[dots[u].rs]);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;cin >> T;
while(T--){
edgecnt = 0 , lastans = 0;
memset(head,0,sizeof(head));
cin >> n >> m;
for(int i=1;i<=m;i++){
int u , v , l , a;cin >> u >> v >> l >> a;
add_edge(u,v,l,a);
add_edge(v,u,l,a);
e[i] = {u,v,a};
}
dijkstra(1);
kruskal();
dfs(len);
cin >> Q >> k >> maxhigh;
while(Q--){
int v , p;cin >> v >> p;
v = (v + k * lastans - 1) % n + 1 , p = (p + k * lastans) % (maxhigh + 1);
for(int j=29;j>=0;j--){
if(fa[v][j]!=0&&dots[fa[v][j]].val>p)v = fa[v][j];
}
cout << (lastans = road[v]) << "\n";
}
}
return 0;
}

浙公网安备 33010602011771号