ウェイ・アウト[NOI2018] p4768

分析

まず各点の端部への最短パスを見つけます。

私たちは、高度を降順にソート

そして、クラスカル再構築された木を見つけます

すべての答えは、実行可能なサブツリー最短の最小値であります

コード

#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(01 ))。
    一方、(!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 
}

 

おすすめ

転載: www.cnblogs.com/yzxverygood/p/11547136.html