我々は最低限の辞書式順序を保証するためにしたいので、この質問は、非常にシンプルなので、星を維持するための最初の鎖が後方にあるので、我々は、降順を挿入し、エッジをソートする必要があります。私達はちょうど、エッジを開始し、ほとんどの短絡、クエリの1がエッジまでの最短の方法ではありませんする必要があると列挙することによって使用することができます
我々は、この縁部にマーキング場合DIST [V] = DIST [U] +エッジ[i]を、決定することができます。そして、マークされたDFSマークは、木であることが保証しました。
その後、分割統治長さとツリーのサブツリーのノードクエリ鎖の単純な、直接ポイントに。そして、あなたはそれが更新され、クエリが実際に以前の質問に非常に似て保存することができ、保存されたMPを対応する点の数と最長チェーン、そうすることができますチェーン、ツリー内のノード数際にサブ列挙、ノードクエリの数は、他のサブツリー、および現在のノード鎖正当鎖があるかどうか。
。。。外側にオープンヘアmaxlinkのための重心を見つけ、最も長いチェーンが内部エラーを維持します。。。メンテナンスの配列を開き、各ノードではないであろう。。。どのように奇妙な。。。
#include <iostreamの> する#include <stdio.hに> する#include <string.hの> する#include <アルゴリズム> の#include <キュー> の#include <ベクトル> の#define PII対<整数、整数> 使用して名前空間std。 const int型INF = 0x3f3f3f3f。 const int型MAXX = 2E5 + 6。 構造体のエッジ{ int型V、W次の、使用。 } E [MAXX]。 INTのTOT、根、N、M、K、L、R、サイズ、ANS、ANS1。 INT SZ [MAXX]、VIS [MAXX]、ヘッド[MAXX]、DIS [MAXX]、ID [MAXX]、Q [MAXX]。 INT D [MAXX]、MP [MAXX]、CNT [MAXX]、MX [MAXX]。 構造体ノード{ int型U、V、W。 }エッジ[MAXX]。 構造体QUE { INT LEN、K。 } QUE [MAXX]。 ボイド追加(int型のx、int型のY、int型Z){ E [++ TOT] .V = Y; E [TOT] .W = Z; eは[TOT]は.next =頭部[X];頭部[x]はTOTを=。 E [++ TOT] .V = xであり、e [TOT] .W = Z、E [TOT] .next =頭部[Y];頭部[Y] = TOT。 } ボイドDFS(int型X){ VIS [X] = 1。 {(; I I = E [i]は.next I =ヘッド[X] INT)のため のint V = E [I] .V。 IF(E [I] .USE == 1 && VIS [V]!){ E [i]は.USE = E [I ^ 1] .USE = 2。 DFS(V); } } } ボイドDJI(){ PRIORITY_QUEUE <PII> Q。 以下のために(INT i = 1; iが<= N; iは++){ DIS [I] = INF。 } DIS [1] = 0。 q.push(make_pair(0,1))。 一方、(q.size()){ int型、U = q.top()は、第2。 q.pop(); IF(VIS [U])続けます。 VIS [U] = 1。 {(; I I = E [i]は.next I =ヘッド[U] INT)のため のint V = E [I] .V。 IF(DIS [V]> DIS [U] + E [i]は.W){ DIS [V] = DIS [U] + E [I] .W。 q.push(make_pair(-dis [V]、V))。 } } } のために(INT I = 2; I <= TOT; iは++){ int型、U = E [I ^ 1] .V。 int型のV = E [i]の.V。 IF(DIS [V] == DIS [U] + E [i]は.W){ E [i]を.USE = 1。 } } のmemset(VIS、0、はsizeof(VIS))。 DFS(1)。 } ボイドgetroot(int型のx、int型FA) { SZ [X] = 1; MX [X] = 0; (; I I = E [i]は.next I =ヘッド[X] INT)のために { IF(E [I] .USE <2 || VIS [E [I] .V] || E [I]。 V == FA)続けます。 getroot(E [I] .V、X)。 SZ [X] + = SZ [E [I] .V]。 MX [X] = MAX(MX [x]は、SZ [E [I] .V])。 } MX [X] = MAX(MX [x]は、サイズSZ [X])。 IF(!ルート|| MX [X] <MX [ルート])ルート= xと; } ボイドgetdis(INT U、INT NUM、INT DIST、INT FA) { // COUT << U << "ORZ" << NUM << ENDL。 IF(NUM <= K)QUE [++ R]・K = NUM、QUE [R] .LEN = DIST。 (; I I = E [i]は.next I =ヘッド[U] INT)のために { int型、V = E [I] .V。 // coutの<< V << " "<< E [i]の.USE <<" "<< VIS [V] <<" "<< FA <<"" << NUM <<てendl; IF(E [I] .USE <2 || VIS [V] || V == FA)続けます。 getdis(V、NUM + 1、DIST + E [I] .W、U)。 } } ボイドslove(INT U){ VIS [U] = 1。 R = 0。 (; iは、I = E [I] .next [U] I =ヘッドINT)のための { int型のV = E [i]の.V。 IF(E [I] .USE <2 || VIS [V])続けます。 INT TMP = R。 getdis(V 1、E [I] .W、U)。 用(int型J = TMP + 1、J <= R; J ++) { int型DIST = QUE [J] .LEN。 int型NUM = queの[J] .K。 もし(MP [K-NUM]> - 1) { IF(DIST + MP [K-NUM]> ANS)ANS = DIST + MP [K-NUM]、ANS1 = CNT [K-NUM]。 そうであれば(DIST + MP [K-NUM] == ANS)ANS1 + = CNT [K-NUM]。 } } のための(INT J = TMP + 1、J <= R; J ++) { int型NUM = QUE [J]・K、DIST = QUE [J] .LEN。 IF(DIST> MP [NUM])MP [NUM] = DIST、CNT [NUM] = 1。 それ以外の場合(DIST == MP [NUM])CNT [NUM] ++; } } ながら(R)MP [QUE [R]・K] = - 1、CNT [QUE [R]・K] = 0、r--の。 (; I I = E [i]は.next I =ヘッド[U] INT)のために { int型、V = E [I] .V。 IF(E [I] .USE <2 || VIS [V])続けます。 ルート= 0; サイズ= SZ [V]。 getroot(V、U); slove(ルート)。 } } BOOL CMP(ノードA、ノードB){ IF(AU == BU){ IF(AV == BV){ 戻りAW <BW。 } 戻りAV <BV。 } AU <BU返します。 } int型のmain(){ scanf関数( "%D%D%D"、&N、&M、およびK); k--; (I 1 = int型; I <= M; iが++){ため のscanf([I] .U "%D%D%D"、およびエッジ・エッジ[I] .V、&エッジを[I] .W)。 ソート(エッジ+ 1、エッジ+ 1 + M、CMP)。 TOT = 1。 memset(CNT、0、はsizeof(CNT))。 memsetの(頭、0、はsizeof(ヘッド))。 (I = M int型; I> = 1; I - )は{ ([I] .W [I] .U、エッジ[I] .V、エッジエッジ)を追加します。 } DJI()。 memsetの(VIS、0、はsizeof(VIS))。 ルート= 0; サイズ= N。 getroot(1,0)。 以下のために(INT i = 1; iは= Kを<; iは++)MP [I] = - 1。 CNT [0] = 1; slove(ルート)。 printf( "%D%D \ n"は、ANS、ANS1)。 0を返します。 }