SDOI2013 直徑(樹的直徑)

2022-04-29 22:15:14 字數 1779 閱讀 9512

小q最近學習了一些圖論知識。根據課本,有如下定義。樹:無迴路且連通的無向圖,每條邊都有正整數的權值來表示其長度。如果一棵樹有n個節點,可以證明其有且僅有n-1 條邊。

路徑:一棵樹上,任意兩個節點之間最多有一條簡單路徑。我們用 dis(a,b)表示點a和點b的路徑上各邊長度之和。稱dis(a,b)為a、b兩個節點間的距離。

直徑:一棵樹上,最長的路徑為樹的直徑。樹的直徑可能不是唯一的。

現在小q想知道,對於給定的一棵樹,其直徑的長度是多少,以及有多少條邊滿足所有的直徑都經過該邊。

輸入格式:

第一行包含乙個整數n,表示節點數。 接下來n-1行,每行三個整數a, b, c ,表示點 a和點b之間有一條長度為c的無向邊。

輸出格式:

共兩行。第一行乙個整數,表示直徑的長度。第二行乙個整數,表示被所有直徑經過的邊的數量。

輸入樣例#1:複製

63 1 1000

1 4 10

4 2 100

4 5 50

4 6 100

輸出樣例#1:複製

1110

2【樣例說明】 直徑共有兩條,3 到2的路徑和3到6的路徑。這兩條直徑都經過邊(3, 1)和邊(1, 4)。

對於100%的測試資料:2<=n<=200000,所有點的編號都在1..n的範圍內,邊的權值<=10^9。

這道題目比較玄學。

我們知道對一顆樹不止一條直徑,那麼被所有直徑經過的邊,

隨著直徑的分叉而不斷收縮。

而直徑的分叉點一定是在直徑上的。

但是我並不知道為什麼要從起點推一遍收縮的一段,再從樹的直徑的末尾推一遍收縮的另一端。這兩段之間的路徑就是解。

但是一遍迴圈是推不出的,必須迴圈兩次??

如果有巨佬乙個迴圈搞出了兩個段點可以告訴本蒟蒻qwq。

#include#include#include#include#include#define ll long long

using namespace std;

const int n=200001;

ll dis[n],maxx,s,t;

ll n,m,num,head[n],vis[n];

struct nodee[n<<1];

ll dep[n],ff[n],l,r,ans,son[n];

void add(int from,int to,ll v)

ll read()

while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();

return x*w;

}void dfs(int x,int fa)

}void dfs2(int u,int fa)

dep[u]=maxn;

}int main()

dfs(s,0);maxx=0;

for(int i=1;i<=n;i++)if(dis[i]>maxx)maxx=dis[i],t=i;

printf("%lld\n",maxx);

l=t;r=s;

int now=t;

while(now!=s)

now=t;

while(now!=s)

now=s;

while(now)

while(l!=r&&l)

printf("%lld\n",ans);

return 0;

}

SDOI2013 直徑(樹的直徑必經邊)

題目傳送 sol 先求出任一直徑同時把直徑拎出來,樹的非直徑部分全部掛在直徑上 如下 對於直徑上的每乙個點i,如果存在它到非直徑上點的最大距離 g i 等於它到直徑兩端點中較短的那一段 d i 則說明這一段也可以成為直徑中的一部分。而我們需要得到所有直徑的交,畫圖可以發現假設兩端 以中點為界 都存在...

SDOI2013 刺客信條

故事發生在1486 年的義大利,ezio 原本只是乙個文藝復興時期的貴族,後來因為家族成員受到聖殿騎士的殺害,決心成為一名刺客。最終,憑藉著他的努力和出眾的天賦,成為了傑出的刺客大師,他不僅是個身手敏捷的武林高手,飛簷走壁擅長各種暗殺術。刺客組織在他的帶領下,為被剝削的平民聲張正義,趕跑了原本統治義...

SDOI2013 保護出題人

出題人銘銘認為給sdoi2012 出題太可怕了,因為總要被罵,於是他又給sdoi2013 出題了。參加sdoi2012 的小朋友們釋放出大量的殭屍,企圖攻擊銘銘的家。而你作為sdoi2013的參賽者,你需要保護出題人銘銘。殭屍從唯一一條筆直道路接近,你們需要在銘銘的房門前放置植物攻擊殭屍,避免殭屍碰...