P1395 會議(樹上找一點到所有點距離和最小)

2021-10-04 19:30:45 字數 1649 閱讀 6711

題意:一顆n個點的樹,n-1條邊,每條邊的權值為1,找到乙個點,使得所有點到這個點的距離之和最小。

思路:我們假設點1為根時,總花費為f[1],假設點2是點1的子節點,那麼f[2]=f[1]-點2的子節點個數+(n-點2的子節點個數),因為我們把根從1換到2的時候,2的子樹中節點貢獻全部-1,其他節點貢獻全部+1。所以我們以1位根節點dfs一遍,找出每個節點的子樹節點數量,再dfs算出以1為根時的代價花費,最後dfs算出每個點的花費,最後輸出最小花費點和最小花費就行了。主要是式子不好想。

#include

using

namespace std;

const

int n=

2e5+5;

const

int inf=

0x7fffffff

;const

int mod=

1e9+7;

const

int eps=

1e-6

;typedef

long

long ll;

typedef

unsigned

long

long ull;

#define ls p<<1

#define rs p<<1|1

#define fi first

#define se second

#define mp make_pair

#define pb push_back

#define pii pair

#define int long long

#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

#define endl '\n'

#define null null

int head[n]

,nxt[n]

,to[n]

,tot=0;

void

add(

int u,

int v)

int s[n]

,f[n]

;int

dfs(

int x,

int y)

return s[x];}

void

dfs2

(int x,

int y,

int z)

}int res,n,pos;

void

dfs3

(int x,

int y)

signed

main()

dfs(1,

0);for

(int i=head[1]

;i;i=nxt[i]

)dfs2

(to[i],1

,1);

for(

int i=head[1]

;i;i=nxt[i]

)dfs3

(to[i],1

);res=f[1]

;pos=1;

for(

int i=

1;i<=n;i++)}

cout<' '<}

洛谷P1395 會議 題解

題目 為什麼這個題會有圖論的標籤啊,雖然圖論也包括找樹的重心,可是這很容易讓人聯想到最短路,但不得不說,這是乙個典型的找樹的重心模板題。樹的重心是什麼?找到乙個點,其所有的子樹中最大的子樹節點數最少,則這個點便是樹的重心。而我們找樹的重心該怎麼找呢,我們可以從定義入手,我們可以搜尋。我們先設任意乙個...

洛谷 P1395 會議(樹的重心)

為什麼要找樹的重心呢?假設我們已經找到了樹的重心,如果把開會地點從重心向右移走,那麼對答案的貢獻就是 左邊的元素和 右邊的元素和。而因為是樹的重心,所以向右移走後左面的元素數量一定大於右面的元素數量,所以ans是比在重心的情況大的,所以最終我們選擇重心。include include include...

找素數的一點思考

2016.7.17 本文 均由c 編寫 經典的素數判定演算法是這樣 給定乙個正整數n,用2到sqrt n 之間的所有整數去除n,如果可以整除,則n不是素數,如果不可以整除,則n就是素數。所以求小於n的所有素數程式如下 include include using namespace std defin...