洛谷 P1268 樹的重量

2021-07-24 11:47:47 字數 1855 閱讀 6117

題目描述

樹可以用來表示物種之間的進化關係。一棵「進化樹」是乙個帶邊權的樹,其葉節點表示乙個物種,兩個葉節點之間的距離表示兩個物種的差異。現在,乙個重要的問題是,根據物種之間的距離,重構相應的「進化樹」。

令n=,用乙個n上的矩陣m來定義樹t。其中,矩陣m滿足:對於任意的i,j,k,有m[i,j] + m[j,k] >= m[i,k]。樹t滿足:

1.葉節點屬於集合n;

2.邊權均為非負整數;

3.dt(i,j)=m[i,j],其中dt(i,j)表示樹上i到j的最短路徑長度。

如下圖,矩陣m描述了一棵樹。

樹的重量是指樹上所有邊權之和。對於任意給出的合法矩陣m,它所能表示樹的重量是惟一確定的,不可能找到兩棵不同重量的樹,它們都符合矩陣m。你的任務就是,根據給出的矩陣m,計算m所表示樹的重量。下圖是上面給出的矩陣m所能表示的一棵樹,這棵樹的總重量為15。

輸入輸出格式

輸入格式:

輸入資料報含若干組資料。每組資料的第一行是乙個整數n(2 < n < 30)。其後n-l行,給出的是矩陣m的乙個上三角(不包含對角線),矩陣中所有元素是不超過100的非負整數。輸入資料保證合法。

輸入資料以n=0結尾。

輸出格式:

對於每組輸入,輸出一行,乙個整數,表示樹的重量。

輸入輸出樣例

輸入樣例#1:

5 5 9 12 8

8 11 7

5 1

4 4

15 36 60

31 55

36 0

輸出樣例#1:

15 71

【分析】

構造+列舉

以下**洛谷題解

鍛鍊思維的好題,需要運用一些樹的性質。以下用g(i,j)表示點i與點j之間的距離。

首先,我們考慮n=2時的情況,很顯然答案就是g(1,2)。

接下來考慮n=3時的情況。由於所有點均為葉子節點,很顯然點3是從點1到點2的路徑上分叉出來的,就像下圖。

設藍色部分長度為len,那麼答案就是g(1,2)+len。len怎麼求呢?顯然,len = (g(1,3)+g(2,3)-g(1,2))/2。

n>3的情況也同理。列舉i,看看點n是不是從點1~i的路徑上分叉出來的,求出的最小len就是要加到答案裡面去的。如下圖。

如果認為點4是從1~2的路徑上分叉出來的,答案就會加上紅色部分的長度。但是紅色部分長度顯然有一部分是多餘的。只有認為點4是從1~3的路徑上分叉出來的,才能加上正確答案(也就是藍色部分)。

【**】

//樹的重量 

#include

#include

#include

#include

#include

#include

#define ll long long

#define m(a) memset(a,0,sizeof a)

#define fo(i,j,k) for(i=j;i<=k;i++)

using

namespace

std;

int a[35][35];

int n;

int main()

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

}return

0;}

洛谷 P1268 樹的重量()

構造法。鍛鍊思維的好題,需要運用一些樹的性質。以下用g i,j 表示點i與點j之間的距離。首先,我們考慮n 2時的情況,很顯然答案就是g 1,2 接下來考慮n 3時的情況。由於所有點均為葉子節點,很顯然點3是從點1到點2的路徑上分叉出來的,就像下圖。設藍色部分長度為len,那麼答案就是g 1,2 l...

洛谷P1268 樹的重量

因為所有的節點都是葉節點,因此每個葉節點都是從已有的節點中分出來的 而每個節點都可以從 1 j j i 中分出 當然類似於floyd三層迴圈列舉也可以 設i為要插入的節點 j為dis 1 j 中最小的那個 jfloyd的話是 for int i 3 i n i ans minn 其中i為要插入的節點...

洛谷 P1268 樹的重量

構造類題目,看不出個所以然來。emmm,只好看題解 只有兩個點,那一條路徑就是 ans 考慮三個點,那麼 3 這個點相對於樹上的路徑 已經加入樹上的邊的距離 為 dis 1 3 dis 2 3 dis 1 2 2 秒啊,這樣就可以求出那一條藍邊的長度了 考慮四個點的情況 對於第四個點,我們發現單純只...