20250807簡單樹上問題

引入

樹是一種特殊的圖,因其看起來像一顆倒掛的樹而得名。
樹有許多等價的形式化定義,我們這里只取一個:nnn個點n?1n-1n?1條邊的無向連通圖。

這是一顆樹

樹的直徑

定義樹上任意兩點之間最長的簡單路徑為樹的直徑。
一棵樹可能有很多直徑,如菊花圖等。

DFS求法

在沒有負邊權的情況下,我們一般使用兩次DFS求樹的直徑:
第一次DFS從任意位置出發,找到距離起點最遠的點x,xx,xxx是一條直徑的端點之一;
第二次DFS從點xxx出發,找到距離點xxx最遠的點yyyxxxyyy的路徑即為一條直徑。

證明&實現

https://oi-wiki.org/graph/tree-diameter/#%E8%BF%87%E7%A8%8B

樹形DP

有負邊權的情況下,不能使用DFS求法,這時就需要用到樹形DP來求解。
任取一個節點作為根節點,對于每個節點xxx,考慮以xxx為根節點的子樹中經過xxx的最長的路徑,這個路徑長度等于xxx向下的最長路徑長度+次長路徑長度,DFS時分別記錄這些信息即可。

實現

void dfs(int u,int fa){d1[u]=d2[u]=0;     //d1是最長路,d2是次長路for(int v:E[u]){if(v==fa)continue;dfs(v,u);int dv=d1[v]+1;if(dv>d1[u]){d2[u]=d1[u];d1[u]=dv; }else if(dv>d2[u]){d2[u]=dv;}}ans=max(ans,d1[u]+d2[u]);
}

樹的重心

選擇一個合適的根節點,使得根節點的子樹能夠盡可能的“均勻”,
這個根節點就是樹的重心。
如何量化“均勻”呢,我們這里把最大子樹節點數認為是“均勻”的程度,
最大子樹節點數越小,就越均勻。使得最大子樹節點數最小的根節點,就是重心。

性質

●樹的重心最多只有兩個,若有兩個一定相鄰。
●以重心作為根節點,根節點的最大子樹節點數不會超過n/2n/2n/2
●樹上所有點到某個點的距離之和中,到重心的最小。
●把兩棵樹用一條邊連起來,形成的新的樹的重心在原來兩樹重心之間的路徑上。
●在一顆樹上添加一個葉子節點,重心最多向葉子節點移動一條邊。

求法

從任意一點作為根節點出發做DFS,求每個節點的子樹節點數,就能知道每個節點作為根節點時的子樹大小,向下的子樹大小直接統計,向上的子樹大小等于n?size[now]n - size[now]n?size[now]

實現

int size[N],mx[N];
void dfs(int u,int fa){for(int v:E[u]){if(v==fa)continue;dfs(v,u);size[u]+=size[v];mx[u]=max(mx[u],size[v]);     // 向下的子樹大小}size[u]++;mx[u]=max(mx[u],n-size[u]);    // 向上的子樹大小
}

DFS序

樹是一種二維的結構,和一維的序列比起來,樹的結構更加復雜,我們在思考樹上問題的解法時,也常常會先考慮一條(一維序列)上的情況如何求解。

那么有沒有一種方法,可以把一顆二維的樹,拍扁壓縮降維成一個序列呢?我們按照DFS的順序,記錄每個節點第一次被訪問到的時間,這就是樹的序列化——DFS序(DFN)

性質

DFS有一些神奇的性質,比如一顆子樹內的每個節點一定都是連續訪問的,
所以一顆子樹內的節點的DFS序可以用一個區間表示,
結合我們之前學過的區間查詢/區間修改,我們就可以在樹上做更多操作。

實現

int dfn[N],size[N],id[N],time;
// dfn[i]表示第i個點的dfs序是dfn[i]
// id[i]表示dfs序為i的點是id[i]
// 第i個點的子樹的dfn區間如何表示?
// [dfn[i], dfn[i] + size[i] - 1]
void dfs(int u,int fa){dfn[u]=++time;id[time]=u;for(int v:E[u]){if(v==fa)continue;dfs(v,u);size[u]+=size[v];}size[u]++;
}

最近公共祖先(LCA)

兩個點的最近公共祖先,就是兩點的公共祖先中距離根節點最遠的那個點。

暴力求法

兩個點中較深的點跳到它自己的父節點,重復該操作直到兩點相遇,此時位置即為LCA。
時間復雜度O(n)O(n)O(n),空間復雜度O(1)O(1)O(1)

倍增求法

我們可以通過倍增預處理出每個點的2k2^k2k級祖先,先把兩點移動到相同的高度,如果兩點不相同,就可以利用倍增數組logloglog求得最遠的不相同的祖先節點,該點的父節點即為LCA。

int fa[20][N];    // 倍增數組,fa[i][x] 表示x號節點的2^i級祖先
int dep[N];
int lca(int a,int b){
//  while(dep[a]<dep[b])b=fa[0][b];if(dep[a]<dep[b])swap(a,b);const int k=dep[a]-dep[b];for(int i=0;i<=19;i++){if(k>>i&1){a=fa[i][a];}}if(a==b)return a;for(int i=19;i>=0;i--){if(fa[i][a]!=fa[i][b]){a=fa[i][a];b=fa[i][b];}}return fa[0][a];
}

DFN上ST表求法

首先處理出dfn,然后在dfn上建st表維護區間內距離根節點最近的節點。
查詢lca時,設最小dfn為lll,最大dfn為rrr
只需要查詢[l+1,r][l + 1, r][l+1,r]區間內距離根節點最近的節點,該節點的父節點即為lca。

int dfn[N], size[N], id[N], time, dep[N];
int st[20][N];
void init() {for (int i = 1; i <= n; i++) {st[0][i] = id[i];}for (int i = 1, p = 1; i < 20; i++, p <<= 1) {for (int j = 1; j + p * 2 - 1 <= n; j++) {st[i][j] = dep[st[i-1][j]] < dep[st[i-1][j+p]] ?st[i-1][j] : st[i-1][j+p];}}
}
int lca(int a, int b) {if (a == b) return a;int l = dfn[a], r = dfn[b];if (l > r) swap(l, r);
//    [l + 1, r]l++;int len = r - l + 1;int k = lg2[len];if (dep[st[k][l]] < dep[st[k][r-(1<<k)+1]]) {return fa[st[k][l]];} else {return fa[st[k][r-(1<<k)+1]];}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918401.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918401.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918401.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

諾基亞就4G/5G相關專利起訴吉利對中國汽車及蜂窩模組企業的影響

諾基亞于2025年7月18日向歐洲統一專利法院&#xff08;UPC&#xff09;曼海姆分庭和德國慕尼黑法院提起訴訟&#xff0c;控訴中國吉利控股集團及其極氪、領克、路特斯、Smart等關聯品牌在未經許可的情況下使用諾基亞4項蜂窩通信標準必要專利 。涉案專利包括1項覆蓋4G/5G的標準必…

Kotlin反射詳解

反射是一種機制&#xff0c;它允許我們在運行時檢查、修改和操作類或對象的內部結構。反射開啟了動態編程的可能性&#xff0c;在開發庫、框架或工具等場景中非常有用。Java 中的反射 在 Java 中&#xff0c;反射一直是實現動態編程的重要基石。它允許開發者在不提前知道類名的…

學習嵌入式-IMX6ULL學習——中斷

volatile&#xff1a;易變的&#xff0c;防止系統優化對寄存器做處理的時候使用&#xff0c;在進行寫1清零操作時&#xff0c;防止該操作被系統優化&#xff1b;一、GIC通用中斷控制器1.GIC通用中斷控制器GIC接收眾多外部中斷&#xff0c;然后對其進行處理&#xff0c;最終通過…

HENGSHI SENSE 6.0 功能-AI 查數助手

面向所有AI Agent開放BI和數據分析能力 AI 查數助手 6.0版本中&#xff0c;我們AI助手的優化是比較深入且全面的。從問答效率到集成能力&#xff0c;都得到了大的躍升&#xff0c;是智能問數應用場景的重大升級以及體驗的全方位優化。我們優化了 AI 助手執行流程&#xff0c;…

降壓型DCDC電源芯片推薦-芯伯樂XBL4001 40V/5A

在電子設備不斷追求高性能與低功耗的今天&#xff0c;電源管理芯片的重要性不言而喻。芯伯樂主推的XBLW-XBL4001芯片&#xff0c;憑借其出色的設計與穩定的性能&#xff0c;為電源管理領域帶來了一款實用的新選擇。一、芯片概述XBLW-XBL4001是一款降壓型&#xff08;Buck&#…

uni-app app端安卓和ios如何申請麥克風權限,喚起提醒彈框

代碼包含功能如下&#xff1a; 1、判斷推送權限是否開啟 2、判斷定位權限是否開啟 3、判斷麥克風權限是否開啟 4、判斷相機權限是否開啟 5、判斷相冊權限是否開啟 6、判斷通訊錄權限是否開啟 7、判斷日歷權限是否開啟 8、判斷備忘錄權限是否開啟 9、Android權限查詢 10、檢查系…

關于 Rust 異步(無棧協程)的相關疑問

這是一個記錄問題求助的文章。關于 waker 與運行時的合作方式我膚淺地學習了 Rust 異步底層實現原理&#xff0c;關于 Future、waker 和運行時等。關于 waker 我有三點猜測&#xff1a;waker 是由實現執行器的人提供的在執行器中會調用 epoll_wait&#xff0c;epoll 返回 fd&am…

stm32項目(25)——基于stm32的植物生長箱環境監測系統

1.實現功能 測 環境溫濕度、光照強度、土壤濕度、水箱水位 手機APP顯示 溫度過低-->打開加熱板 濕度過低-->打開水泵 土壤濕度低-->開水泵 --->只要有指標低于閾值時 就蜂鳴器報警 光強弱-->補光 水位低-->抽水 OLED屏幕實時顯示各種信息 分…

golang 基礎案例_02

1.鎖有時候我們的代碼中可能會存在多個 goroutine 同時操作一個資源&#xff08;臨界區&#xff09;的情況&#xff0c;這種情況下就會發生競態問題&#xff08;數據競態&#xff09;。(1)、互斥鎖&#xff1b;(2)、讀寫互斥鎖&#xff1b;(3)、sync.WaitGroup&#xff1b;(4)、…

C++算法·前綴和

前綴和(Prefix(Prefix(Prefix Sum)Sum)Sum)的定義 前綴和是一種高效處理區間求和問題的算法技巧 其核心思想是通過預處理構建一個前綴和數組 使得后續的區間和查詢可以在常數時間O(1)O(1)O(1)內完成 核心概念 定義 給定一個數組a[1...n]a[1...n]a[1...n],其前綴和數組s[1...…

JavaEE 初階第十七期:文件 IO 的 “管道藝術”(下)

專欄&#xff1a;JavaEE初階起飛計劃 個人主頁&#xff1a;手握風云 目錄 一、Java文件內容寫入 1.1. OutputStream 二、字符流讀取和寫入 2.1. Reader 2.2. Writer 三、示例練習 3.1. 查找文件功能 一、Java文件內容寫入 1.1. OutputStream OutputStream同樣只是?個抽…

【liunx】web高可用---nginx

NGINX簡介Nginx&#xff08;發音為 “engine x”&#xff09;是一款由俄羅斯程序員 Igor Sysoev 開發的 輕量級、高性能的 HTTP 和反向代理服務器&#xff0c;同時也是一個 IMAP/POP3/SMTP 代理服務器。自 2004 年首次發布以來&#xff0c;Nginx 憑借其 高并發處理能力、低內存…

FPGA+護理:跨學科發展的探索(二)

FPGA護理&#xff1a;跨學科發展的探索&#xff08;二&#xff09; 系列文章目錄 FPGA護理&#xff1a;跨學科發展的探索&#xff08;一&#xff09; 文章目錄FPGA護理&#xff1a;跨學科發展的探索&#xff08;二&#xff09;系列文章目錄引言三、FPGA 在精神醫學護理中的應用…

localforage的數據倉庫、實例、storeName和name的概念和區別

在 localForage 中&#xff0c;數據倉庫、實例、storeName 和 name 是核心概念&#xff0c;用于管理底層存儲&#xff08;IndexedDB/WebSQL/localStorage&#xff09;。以下是詳細解釋和區別&#xff1a; 1. 數據倉庫 (Database) 定義&#xff1a;指底層的物理數據庫&#xff…

使用MAS(Microsoft Activation Scripts)永久獲得win10專業版和office全套

文章目錄Microsoft Activation Scripts簡介下載地址使用方法Microsoft Activation Scripts簡介 MAS是Microsoft Activation Scripts縮寫。 主要提供如下功能&#xff1a; 使用該腳本可以永久獲得win10專業版和office全套&#xff08;可選&#xff09; 下載地址 https://pan…

零 shot 語義+在線閉環:深度學習讓機器人學會“主動”

來gongzhonghao【圖靈學術計算機論文輔導】&#xff0c;快速拿捏更多計算機SCI/CCF發文資訊&#xff5e;在當下&#xff0c;機器人與深度學習的融合正成為AI領域的核心發展趨勢&#xff0c;相關研究在頂會頂刊上熱度居高不下。從ICLR到CoRL&#xff0c;諸多前沿成果不斷涌現&am…

Nginx學習筆記(三)——在 CentOS 7 中配置阿里云鏡像源

&#x1f4da; Nginx學習筆記&#xff08;三&#xff09;——在 CentOS 7 中配置阿里云鏡像源 在 CentOS 7 中配置阿里云鏡像源可顯著提升軟件安裝和更新的速度&#xff0c;以下是詳細操作步驟&#xff1a; &#x1f527; 配置阿里云鏡像源步驟 1?? 備份原有源配置 sudo mv /…

WebSocket--簡單介紹

一、什么是 WebSocket&#xff1f;定義&#xff1a;WebSocket 是一種在單個 TCP 連接上進行全雙工通信的協議。作用&#xff1a;實現客戶端&#xff08;瀏覽器&#xff09;和服務器之間的實時、雙向通信。優勢&#xff1a;連接保持&#xff0c;通信實時性強&#xff08;不像 HT…

【STM32 LWIP配置】STM32H723ZG + Ethernet +LWIP 配置 cubemx

STM32H723ZG LAN8742 Ethernet LWIP 配置 cubemx &#x1f31e;這邊記錄一下這塊mcu 配置以太網的過程&#xff0c;IDE是KEIL MDK&#xff0c;其實就是在下面多次提到的blog的基礎上 在scatter file進行配置 首先&#xff0c;如果想要簡單一點 直接去cubemx 那邊獲取相關的例…

EI檢索-學術會議 | 人工智能、虛擬現實、可視化

第五屆人工智能、虛擬現實與可視化國際學術會議&#xff08;AIVRV 2025&#xff09;定于2025年9月5-7日在中國 成都召開。人工智能正驅動各行業智能化轉型&#xff0c;提升效率與質量&#xff1b;虛擬現實技術以其沉浸感重塑教育、娛樂、醫療等領域體驗&#xff1b;可視化技術…