給定一棵無根樹,假設它有n個節點,節點編號從1到n, 求任意兩點之間的距離(最短路徑)之和。
第一行包含乙個正整數n (n <= 100000),表示節點個數。
後面(n - 1)行,每行兩個整數表示樹的邊。
output每行乙個整數,第i(i = 1,2,...n)行表示所有節點到第i個點的距離之和。
4
1 23 2
4 2
535
5
思路:樹形dp?
dp[u]表示以結點u到其子樹所有結點的距離和;
cnt[u]表示包括u在內的子樹中所有結點個數;
v為u的子結點,則有: cn
t[u]
=(∑c
nt[v
])+1
這個好理解,子節點之和加上自己 dp
[u]=
∑(dp
[v]+
cnt[
v])
這樣理解:dp
[u]=
∑dp[
v]+∑
cnt[
v],所有子節點的子節點距離和+每個子節點需要多走一步。
所以可以從葉子結點往上進行狀態轉移,直至算出根節點的dp值又注意到若dp[u]表示u到其他所有結點的距離和,v為u的子結點,則有: dp
[v]=
dp[u
]−cn
t[v]
+(n−
cnt[
v])
dp[v
]=dp
[u]+
n−2∗
cnt[
v]v子樹中的所有結點的到v的距離比其到u的距離的各少1,共cnt[v]個結點,則需要減去cnt[v]
不在v子樹中的所有結點到v的距離比其到u的距離各多1,共n−cnt[v]個結點,則需要加上n−cnt[v]
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
const
int maxn= 1e5+100;
vector
node[maxn];
long
long dp[maxn];
long
long cnt[maxn];
int n;
void dp_up(int u,int p)
}}void dp_down(int u,int p)
}}int main ()
dp_up(1,0);
dp_down(1,0);
for(int i=1;i<=n;i++)
}
51nod 1405 樹的距離之和
給定一棵無根樹,假設它有n個節點,節點編號從1到n,求任意兩點之間的距離 最短路徑 之和。input 第一行包含乙個正整數n n 100000 表示節點個數。後面 n 1 行,每行兩個整數表示樹的邊。output 每行乙個整數,第i i 1,2,n 行表示所有節點到第i個點的距離之和。input示例...
51Nod 1405 樹的距離之和
acm模版 根據題意,這是一顆樹,所以每兩點之間的路徑一定是唯一的。這裡讓求所有點到第i個結點的距離和,其實也就是其他所有結點到第i個結點的距離和。通過觀察發現,只要我們找到了乙個點對應的結果,那麼其他所有的點都可以通過這個結果擴充套件出來,利用邊的關係。比如說,我們知道了第乙個結點對應的結果,並且...
51nod 1405 樹的距離和
題意 有n個節點的無根樹,求每個節點分別到其他n 1個節點的距離之和。思路 設dp x 表示節點x到其他n 1個節點的距離和。乙個dp x 是很好求的,把x當成根,一遍dfs,把所有點的深度加起來,就可以求出dp x 得知dp x 如何求得dp y 呢?此時x是父節點,y是兒子節點。我們再增加乙個兒...