分析
まず各点の端部への最短パスを見つけます。
私たちは、高度を降順にソート
そして、クラスカル再構築された木を見つけます
すべての答えは、実行可能なサブツリー最短の最小値であります
コード
#include <ビット/ STDC ++ H>
使用して 名前空間STDを、
#define Fiの第一
の#define SE第二
の#define MP make_pair用
の#defineのLi長い長い
int型ヘッド[ 800100 ]、NXT [ 800100 [する]、800100 [W]、800100 ]、N、M、CNT。
INT [DIS 800100 ]、VIS [ 800100 ]、TOT、PR [ 800100 ] [ 23 ]、FA [ 800100 ]、ヴァル[ 800100 ]。
ベクター < INT > V [ 800100 ]。
構造体ノード{
intはX、Y、Z、W。
}。
ノードD [ 400100 ]。
インラインブール CMP(CONSTノードx、CONSTノードy){ 戻り XW> YW;}
インラインINT SF(INT X){ 戻り FA [X] == X X:FA [X] = SF(FA [X]) ;}
構造体Kruskal_Tree {
インラインボイドビルド(){
int型 I、J、K = 0 。
用(i = 1 iは++; iは、M <= N + V [i]は.clearを())。
TOT = N;ソート(D + 1、D + M +1 、CMP)。
用(i = 1、FA [I] = iは++; iは、M <= N +)、I。
用(i = 1 ; I <= M; iは++ ){
int型、X = D [i]が.Xは、Yは= D [i]が.Y、Z = D [i]は.W。
もし(!SF(X)= SF(Y)){
V [ ++ TOT] .push_back(SF(X));
V [TOT] .push_back(SF(Y))。
FA [SF(X)] = FA [SF(Y)] = TOT。
ヴァル[TOT] = Z;
K ++ ;
}
もし(K == N- 1)ブレーク。
}
}
インラインボイド DFS(int型のx、int型FA){
PR [X] [ 0 ] = FA。
以下のために(int型 i = 0 ; iはV <[X] .size(); iは++ )
場合(V [x]は[I] =!FA){
DFS(V [X] [i]は、X)。
DIS [X] = 分(DIS [x]は、DIS [V [X] [I])。
}
}
インラインボイド取引(){
ため(int型 i = 1 ; iは<= 20 ; I ++ )
のための(INT J = 1); J <= TOT; J ++
PR [J] [I] = PR [PR [J] [I- 1 ]] [I- 1 ]。
}
インラインINT QUE(int型のx、int型のY){
ため(int型 = Iを20 ; I> = 0 ; i--)場合(PR [X] [I] &&ヴァル[PR [X] [I]]> Y) X = PR [X] [I];
リターンのx;
}
}。
Kruskal_Tree T;
PRIORITY_QUEUE <ペア< int型、int型 >> Q;
インラインボイドのinit(){
CNT = 0 。
memsetの(ヘッド、 0、はsizeof (ヘッド))。
memset(DIS、から0x7f、はsizeof (DIS))。
memsetの(VIS、0、はsizeof (VIS))。
memsetの(PR、0、はsizeof (PR))。
}
インラインボイド追加(int型のx、int型の Y、int型Z){
NXT [ ++ CNT] = 頭部[X]。
ヘッド[X] = CNT。
[CNT]へ = Y。
W [CNT] = Z;
NXT [ ++ CNT] = 頭部[Y]。
ヘッド[Y] = CNT。
[CNT]に =のX。
W [CNT] = Z;
}
インラインボイドをDij(){
DIS [ 1 ] = 0 ;
q.push(MP(0、1 ))。
一方、(!q.empty()){
int型のx = q.top()SE。
q.pop();
もし(VIS [X])続けます。
VIS [X] = 1 。
用(int型 ; I I = I =ヘッド[X] {NXT [i])と
する場合 >(LI)(DIS [X] + [I]乃至] DIS( = DIS [X ] + W [I])){
DIS [する[I] W [i]は、
q.push(MP( - DIS [する[I]、[I])まで)。
}
}
}
}
int型のmain(){
int型は、I、J、K、T、X、Y、Z、Q、S。
scanf関数(" %のD "、&T)。
一方、(t-- ){
INIT()。
scanf関数(" %d個の%のD "、&N、&M)。
用(i = 1 ; I <= M; iは++ ){
scanf関数(" %D%D%D%D "、&D [i]は.X、&D [i]を.Y、&D [i]が.Z、&D [I] .W)。
追加(D [i]が.X、D [i]は.Y、D [i]を.Z)。
T.build();
T.dfs(TOT、
printf(0 );
T.deal();
int型 lastans = 0 ;
scanf関数(" %D%D%D "、&Q、&K&S)。
一方、(q-- ){
scanf関数(" %D%dの"、およびX&Y)。
X =(X + 1LL * K * lastans%N- 1)%のN + 1 。
Y =(Y + 1LL * K * lastans%で(S + 1))%(複数可+ 1 )。
lastans = DIS [T.que(X、Y)]。" %Dを\ n " 、lastans)。
}
}
戻り 0 。
}