AHOI2008 緊急集合 聚會

2021-09-02 01:45:20 字數 2340 閱讀 8805

歡樂島上有個非常好玩的遊戲,叫做「緊急集合」。在島上分散有n個等待點,有n-1條道路連線著它們,每一條道路都連線某兩個等待點,且通過這些道路可以走遍所有的等待點,通過道路從乙個點到另乙個點要花費乙個遊戲幣。

參加遊戲的人三人一組,開始的時候,所有人員均任意分散在各個等待點上(每個點同時允許多個人等待),每個人均帶有足夠多的遊戲幣(用於支付使用道路的花費)、地圖(標明等待點之間道路連線的情況)以及對話機(用於和同組的成員聯絡)。當集合號吹響後,每組成員之間迅速聯絡,了解到自己組所有成員所在的等待點後,迅速在n個等待點中確定乙個集結點,組內所有成員將在該集合點集合,集合所用花費最少的組將是遊戲的贏家。

小可可和他的朋友邀請你一起參加這個遊戲,由你來選擇集合點,聰明的你能夠完成這個任務,幫助小可可贏得遊戲嗎?

輸入格式:

第一行兩個正整數n和m(n<=500000,m<=500000),之間用乙個空格隔開。分別表示等待點的個數(等待點也從1到n進行編號)和獲獎所需要完成集合的次數。 隨後有n-1行,每行用兩個正整數a和b,之間用乙個空格隔開,表示編號為a和編號為b的等待點之間有一條路。 接著還有m行,每行用三個正整數表示某次集合前小可可、小可可的朋友以及你所在等待點的編號。

輸出格式:

一共有m行,每行兩個數p,c,用乙個空格隔開。其中第i行表示第i次集合點選擇在編號為p的等待點,集合總共的花費是c個遊戲幣。

輸入樣例#1:複製

6 4  

1 2

2 3

2 4

4 55 6

4 5 6

6 3 1

2 4 4

6 6 6

輸出樣例#1:複製

5 2

2 54 1

6 0

40%的資料中n<=2000,m<=2000

100%的資料中,n<=500000,m<=500000

分析:首先考慮只有兩個點的情況,很明顯樹上兩點a,b之間距離為$ dep[a]+dep[b]-dep[lca(a,b)] $ (dep表示該點到根節點的距離(即深度))

那麼這給我們的啟示是:對於三個點能不能用也用lca求解

接下來我們就不難發現,對於樹上三點a,b,c,它們兩兩之間都有乙個lca,一共就有三個,這三個中有兩個是同乙個且深度較小

證明:我們假設$ x=lca(a,b),y=lca(a,c),且x>y $

則對於$ z=lca(b,c) $,首先存在路徑$b->x,a->x->y$,則有路徑$b->x->y$,又因為$c->y$,所以$ lca(b,c)=y=lca(a,c) $

接下來我們先找集合點,假設集合點存在於那個較深的lca(即上面的x)

那麼我們不難發現,不管是將x上移還是下移,都會使乙個點的路徑減少$w$,但另兩個點的路徑都會增加$w$

因此將點放在那個較深的lca最優

關於計算路徑,我們用上面所設的點表示出來是

$$ ans=dep[a]+dep[b]-2*dep[x]+dep[x]+dep[c]-2*dep[y]$$

$$=dep[a]+dep[b]+dep[c]-dep[x]+2*dep[y]$$

$$=dep[a]+dep[b]+dep[c]-dep[x]-dep[y]-dep[z](y==z)$$

我們發現不管a,b,c如何變化,由於x,y,z的值不會變化,所以ans的值也不會變化,直接代入求值即可

#include#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

struct

nodesq[

1001000

];int fa[500500][25],n,m,dep[500500],head[500500],all=0,low[500500

];void add(int u,int

v)void dfs(int u,int

fu)}

int lca(int u,int

v)

return fa[u][0];}

intmain()

low[

1]=0

;

for (i=2;i<=n;i++) low[i]=low[i>>1]+1

; dep[

0]=0

; dfs(

1,0);

for (i=1;i<=m;i++)

return0;

}

AHOI2008 緊急集合 聚會

歡樂島上有個非常好玩的遊戲,叫做 緊急集合 在島上分散有n個等待點,有n 1條道路連線著它們,每一條道路都連線某兩個等待點,且通過這些道路可以走遍所有的等待點,通過道路從乙個點到另乙個點要花費乙個遊戲幣。參加遊戲的人三人一組,開始的時候,所有人員均任意分散在各個等待點上 每個點同時允許多個人等待 每...

AHOI2008 緊急集合 聚會

歡樂島上有個非常好玩的遊戲,叫做 緊急集合 在島上分散有n個等待點,有n 1條道路連線著它們,每一條道路都連線某兩個等待點,且通過這些道路可以走遍所有的等待點,通過道路從乙個點到另乙個點要花費乙個遊戲幣。參加遊戲的人三人一組,開始的時候,所有人員均任意分散在各個等待點上 每個點同時允許多個人等待 每...

AHOI2008 緊急集合 聚會

緊急集合 聚會 題目大意 給出乙個無向圖,每一次給出圖中的三個點,求離三個點距離之和最小的點。解決方法 倍增lca。首先我們兩兩點之間求出lca,那麼離他們距離之和最近的點就是三個點中深度最深的點,想一想為什麼?我們假設存在乙個點離三個點距離之和更近且深度更淺,那麼我們將它的深度往下走乙個,一定會有...