洛谷 P1099 樹網的核(樹的直徑 貪心)

2022-04-06 18:09:31 字數 1409 閱讀 4915

用兩邊dfs求出直徑,用f記錄fa,這樣就記錄下了直徑的路徑,將直徑上的點vis標記為1。然後列舉左右端點(或者尺取法,但不會)。

貪心考慮對答案的貢獻:

假設直徑的兩個端點為a和b,當前左右端點為i,j,

對答案的貢獻只有a,i之間的距離、b,j之間的距離、i,j中每個節點的子樹的最遠距離。

那麼可以對於直徑上的每乙個節點做一次關於它的子樹(除直徑)的dfs,找出子樹最遠距離,存在dt中。注意不要每更換一次左右端點就重新求一遍,因為vis

會影響(坑)。

ac**:

1 #include2 #include3 #include4 #include5

using

namespace

std;

6int

n,s;

7const

int n=400;8

int tot,ans=0x7f7f7f7f

,anss,ansss;

9int

head[n];

10int

f[n],maxd,dis[n],diss[n],dt[n];

11int

p,vis[n];

12struct

nodeedge[n<<1

];15

void add(int u,int v,int

w)21

void dfs(int u,int

fa)27

for(int i=head[u];i!=-1;i=edge[i].next)34}

35void dfsd(int

u)44}45

intmain()

54 dfs(1,-1

);55 memset(dis,0,sizeof

(dis));

56 memset(f,-1,sizeof

(f));

57 memset(vis,0,sizeof

(vis));

58int a=p;

59 maxd=0

;60 dfs(p,-1

);61

int b=p;

62 memset(vis,0,sizeof

(vis));

63for(int i=b;i!=-1;i=f[i]) vis[i]=1;64

for(int i=b;i!=-1;i=f[i])

71 anss=max(anss,maxd);72}

73 ans=min(ans,anss);74}

75}76 printf("%d"

,ans);

77return0;

78 }

ac**

洛谷P1099 樹網的核

題目 對於這種題目描述比較長的題,可以考慮簡化題意。簡化後的題意 給定一棵帶邊權無根樹 在其直徑上求出一段長度不超過s的路徑f,使得離路徑距離最遠的點到路徑的距離最短。求最短距離。根據題目範圍,直接暴力floyd求多源最短路徑。然後 n 2 求出直徑和直徑端點。搜尋求出直徑上的點。然後再暴力找出所有...

洛谷 P1099 樹網的核

設t v,e,w t v,e,w 是乙個無圈且連通的無向圖 也稱為無根樹 每條邊到有正整數的權,我們稱tt為樹網 treebetwork 其中vv,ee分別表示結點與邊的集合,ww表示各邊長度的集合,並設tt有nn個結點。路徑 樹網中任何兩結點aa,bb都存在唯一的一條簡單路徑,用d a,b d a...

洛谷 P1099 樹網的核 題解

樓上的大佬似乎都用的dfs,像我這種蒟蒻只會用暴力的floyd演算法。不過,看到這道題規模只有300,floyd演算法不會有問題。首先用floyd演算法預處理點對之間的距離,接下來窮舉每一對點構成的路徑 假裝每一條路徑就是樹網的核 如果路徑長 s,則計算其它點到該路徑的最大距離,取窮舉到的所有路徑中...