輸入檔案包含多組測試資料。對於每組測試資料,第一行乙個整數n (n<=10000),接下來有n-1行,每一行兩個數,對於第i行的兩個數,它們表示與i號電腦連線的電腦編號以及它們之間網線的長度。網線的總長度不會超過10^9,每個數之間用乙個空格隔開。
對於每組測試資料輸出n行,第i行表示i號電腦的答案 (1<=i<=n).
51 1
2 13 1
1 1323
44去掉複雜的題幹,問題其實就是求樹上任意點到其他點的最遠距離。求解的方法有很多,充分利用樹的結構特點,利用樹的直徑。
• 首先回憶一下求樹的直徑的方法
• 假設樹的最長路的兩個葉子節點為v1, v2,從任意一點 u 出發走到的最遠的點一定是(v1,v2)中的一點,然後再從 v1 或者 v2 出發走到的最遠點一定是 v2 或者 v1。由此經過兩次遍歷就能找到最長路徑。
• 這道題不是找最長路徑,是找某個節點 x 所能到達的最長路徑。首先這個節點 x 的最長路徑要麼是到 v1 的路徑,要麼就是到 v2 的路徑。
• 由於不知道往哪邊走才是最長的路徑,所以需要分別從 v1, v2 點再次遍歷共需要三次遍歷。
• 這個題也可以使用樹形動態規劃來解決。
(剛開始一直wa,注意有多組測試資料!!!)參考**如下:
#include
#include
using
namespace std;
struct edge
}a[20010];
int vis[
10010
],vis1[
10010];
int t[
10010];
void
dfs(
int x,
int d)
void
dfs1
(int x,
int d)
intmain()
sort
(a,a+
2*n-2)
; t[1]
=0;t[n+1]
=2*n-2
;for
(int i=
1;i;i++)if
(a[i]
.x!=a[i-1]
.x)t[a[i]
.x]=i;
//求直徑的兩個端點x,y
for(
int i=
1;i<=n;i++
)vis[i]=-
1;dfs(1,
0); x=1;
for(
int i=
2;i<=n;i++)if
(vis[i]
>vis[x]
)x=i;
for(
int i=
1;i<=n;i++
)vis[i]=-
1;dfs(x,0)
; y=1;
for(
int i=
2;i<=n;i++)if
(vis[i]
>vis[y]
)y=i;
for(
int i=
1;i<=n;i++
)vis1[i]=-
1;dfs1
(y,0);
//最用距離為到直徑端點距離的最大值
for(
int i=
1;i<=n;i++)if
(vis1[i]
)printf
("%d\n"
,vis[i]);
else
printf
("%d\n"
,vis1[i]);
}return0;
}
Dijkstra演算法 求一點到任意一點的最短距離)
思路 先找出最短的乙個點,也就是起點,從起點出發,找最短的邊,同時標記起點為true 代表已經訪問過 訪問過的點就不用再訪問了,依次下去,保證每一次找到的邊都是最短的邊 到最後沒有邊可以更新了就代表結束 看 include include include include include includ...
直線外一點到直線的距離
已知直線上兩點求直線的一般式方程 已知直線上的兩點p1 x1,y1 p2 x2,y2 p1 p2兩點不重合。則直線的一般式方程ax by c 0中,a b c分別等於 a y2 y1 b x1 x2 c x2y1 x1y2 直線外一點到直線的距離 p 的座標為 xo,yo 則點 p 到直線 l 的距...
求一顆樹以任意點為根,其他點到根的和
思路 一遍 dfs 可以求到以任意乙個點為根,所有點所含孩子的個數,cnt陣列記錄 考慮每一條邊的貢獻時,即此邊左右節點數相乘 第2遍 dfs,以其他點為根時,例如以2為根,先去掉 0 1 邊的貢獻,再加上以2為根 0和1 對 2 的貢獻 示例 class solution cnt x sum vo...