p4768 [NOI2018]归程
分析
先求出每个点到终点的最短路
我们按照海拔从大到小排序
然后求出kruskal重构树
每次答案就是一个可行子树中的最短路的最小值
代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define li long long
int head[800100],nxt[800100],to[800100],w[800100],n,m,cnt;
int dis[800100],vis[800100],tot,pr[800100][23],fa[800100],val[800100];
vector<int>v[800100];
struct node {
int x,y,z,w;
};
node d[400100];
inline bool cmp(const node x,const node y){return x.w>y.w;}
inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
struct Kruskal_Tree {
inline void build(){
int i,j,k=0;
for(i=1;i<=n+m;i++)v[i].clear();
tot=n;sort(d+1,d+m+1,cmp);
for(i=1;i<=n+m;i++)fa[i]=i;
for(i=1;i<=m;i++){
int x=d[i].x,y=d[i].y,z=d[i].w;
if(sf(x)!=sf(y)){
v[++tot].push_back(sf(x));
v[tot].push_back(sf(y));
fa[sf(x)]=fa[sf(y)]=tot;
val[tot]=z;
k++;
}
if(k==n-1)break;
}
}
inline void dfs(int x,int fa){
pr[x][0]=fa;
for(int i=0;i<v[x].size();i++)
if(v[x][i]!=fa){
dfs(v[x][i],x);
dis[x]=min(dis[x],dis[v[x][i]]);
}
}
inline void deal(){
for(int i=1;i<=20;i++)
for(int j=1;j<=tot;j++)
pr[j][i]=pr[pr[j][i-1]][i-1];
}
inline int que(int x,int y){
for(int i=20;i>=0;i--)if(pr[x][i]&&val[pr[x][i]]>y)x=pr[x][i];
return x;
}
};
Kruskal_Tree T;
priority_queue<pair<int,int> >q;
inline void init(){
cnt=0;
memset(head,0,sizeof(head));
memset(dis,0x7f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(pr,0,sizeof(pr));
}
inline void add(int x,int y,int z){
nxt[++cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
w[cnt]=z;
nxt[++cnt]=head[y];
head[y]=cnt;
to[cnt]=x;
w[cnt]=z;
}
inline void dij(){
dis[1]=0;
q.push(mp(0,1));
while(!q.empty()){
int x=q.top().se;
q.pop();
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
if(dis[to[i]]>(li)(dis[x]+w[i])){
dis[to[i]]=dis[x]+w[i];
q.push(mp(-dis[to[i]],to[i]));
}
}
}
}
int main(){
int i,j,k,t,x,y,z,q,s;
scanf("%d",&t);
while(t--){
init();
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d%d%d",&d[i].x,&d[i].y,&d[i].z,&d[i].w);
add(d[i].x,d[i].y,d[i].z);
}
dij();
T.build();
T.dfs(tot,0);
T.deal();
int lastans=0;
scanf("%d%d%d",&q,&k,&s);
while(q--){
scanf("%d%d",&x,&y);
x=(x+1ll*k*lastans%n-1)%n+1;
y=(y+1ll*k*lastans%(s+1))%(s+1);
lastans=dis[T.que(x,y)];
printf("%d\n",lastans);
}
}
return 0;
}