圖論學習筆記 4 - 仙人掌圖

先扔張圖:


為了提前了解我們采用的方法,請先閱讀《圖論學習筆記 3》。

仙人掌圖的定義:一個連通圖,且每條邊只出現在至多一個環中。

這個圖就是仙人掌圖。

這個圖也是仙人掌圖。

而這個圖就不是仙人掌圖了。

很容易發現,仙人掌圖就是在樹上連了若干條邊( ≥ 1 \ge 1 1 條)。所以可以視為仙人掌圖是基環樹的擴展。


眾所周知,我們通過想象基環樹的深搜樹形態解決了基環樹的一些問題,所以也考慮想象仙人掌圖的深搜樹。

這里就直接給圖了:

很容易發現以下性質:

  • 仙人掌圖中,每一條回邊互不相交且與環一一對應,環由回邊與祖先到子孫的鏈構成。(這個比較顯然,可以簡單理解)

  • 任何一個環的 u p up up 點或者是 d n dn dn 點,其子樹一定包含的是完整的環。

很容易感性理解。 u p up up 的子樹一定包含所有的環點, d n dn dn 的子樹一定不包含所有的環點。所以就可以證了。

  • 在每一個點的子樹中,至多有一個沒有遍歷到其對應的 u p up up 點的 d n dn dn 點。

考慮反證法,設我們有一個點 x x x,其子樹里面有兩個沒有遍歷到其對應的 u p up up 點的 d n dn dn 點。設兩個 u p up up 點為 u p 1 , u p 2 up1,up2 up1,up2,設兩個 d n dn dn 點為 d n 1 , d n 2 dn1,dn2 dn1,dn2

很容易發現,兩個 u p up up 點一定是 x x x 的祖先。不妨這里設 u p 1 up1 up1 u p 2 up2 up2 的祖先。

容易發現, u p 1 up1 up1 x x x 的一整條路徑都出現在了兩個環中,所以這樣是矛盾的,原結論得證。


T425915 仙人掌圖最大獨立集

首先默認已經做過基環樹版本的 騎士 那道題了。

回顧一下那道題的做法,可以發現對于一條回邊 u p → d n up \to dn updn 構成的環,我們是在原有的 沒有上司的舞會那道題 d p dp dp 狀態上進行了一個升維,在記錄子樹根結點有沒有選的同時還記錄了 d n dn dn 有沒有選。

考慮將這種方法擴展到仙人掌圖上面,但是我們發現一個結點的子樹里面可能有很多的 d n dn dn(并不是只有一個環了),而且數量是會變化的,而我們又不可能 2 n 2^n 2n 記錄所有的 d n dn dn 選沒選,所以在狀態設計方面遇到了一點“困難”。

但是我們發現,上述結論 3 就是為我們量身定制的,因為其他已經被考慮過的環已經不用再考慮(這是仙人掌圖,不會出現環套環的情況),所以只需要把目光放在這個沒有走到 u p up up d n dn dn 點就行了。

所以就可以設計狀態了。至此思路已經成型,直接把那道題的代碼拿過來改改就行了。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 50010;
int n;
vector<int> v[N];
int dp[N][4];
bool stk[N], vis[N];
int up[N];
int m;void dfs(int u, int pre) {vis[u] = stk[u] = 1;dp[u][1] = dp[u][3] = 1, dp[u][0] = dp[u][2] = 0;for (auto i : v[u])if (!vis[i]) {dfs(i, u);if (up[i] != 0 && up[i] != u)up[u] = up[i];if (u == up[i]) {dp[u][0] += max(max(dp[i][0], dp[i][1]), max(dp[i][2], dp[i][3]));dp[u][1] += dp[i][0];dp[u][2] += max(max(dp[i][0], dp[i][1]), max(dp[i][2], dp[i][3]));//很容易發現,對于一個環結束的時候,可以取 dp[2] 和 dp[0] 的增量相同,dp[3] 和 dp[1] 的增量相同dp[u][3] += dp[i][0];} else {dp[u][0] += max(dp[i][0], dp[i][1]);dp[u][1] += dp[i][0];dp[u][2] += max(dp[i][2], dp[i][3]);dp[u][3] += dp[i][2];}} else if (i != pre && stk[i])up[u] = i, dp[u][1] = dp[u][2] = -1e16;stk[u] = 0;
}signed main() {cin >> n >> m;for (int i = 1; i <= m; i++) {int x, y;cin >> x >> y;v[x].push_back(y), v[y].push_back(x);}dfs(1, 0);cout << max(dp[1][0], dp[1][1]) << endl;return 0;
}

可以發現,這份代碼和騎士那道題的那份代碼是差不多了,主要改動就是把原來的單個元素 u p up up 變成了一個數組 up[]

最大獨立集時間復雜度

學了這么多獨立集,來總結一下各種圖的求最大獨立集的時間復雜度。

首先對于一般圖,求獨立集屬于 NP 完全問題,也就是只能暴力枚舉。

對于二分圖,設點數 n n n,邊數 m m m,則可以使用網絡流將復雜度變成 O ( m n ) O(m \sqrt n) O(mn ?) 的級別(網絡流還沒學過qwq)。

對于仙人掌圖,也包含了樹和基環樹,可以使用深搜樹 + dp 的方式把復雜度變成 O ( n + m ) O(n+m) O(n+m) 的級別。

對仙人掌圖進行縮點

發現仙人掌是一堆環通過一堆邊拼在一起,兩兩之間彼此不相交。顯然會發現,這個時候若把每一個環都看作是一個點,那么最終就會變成一棵樹,在上面可以跑各種各樣的科技。

那么怎么看作是一個點呢???通過 P5236 的圓方樹做法,我們想到了可以配合點雙連通分量進行縮點。

考慮仙人掌圖中的每一個點雙,不難發現是這樣子的:

  • 每一個點雙恰好是一個簡單環,或者是恰為一條非環邊。

顯然簡單環一定是極大的點雙連通分量,但是剩下的邊中的每一條邊也會變成一個點雙連通分量,所以上面的那句話是正確的。

例如這個仙人掌圖的深搜樹,樹邊用實線,回邊用虛線:

所有的點雙連通分量現在已經用彩色線圈出來了,在旁邊寫上了新的編號。

最終得到的園方樹如下:

以前我們就知道圓方樹有著求必經點和可經點的作用,但是在對仙人掌圖縮點的時候它會有更大的作用。

觀察綠色點雙連通分量,發現其 u p up up 結點為 3 3 3 號結點(這里 u p up up 結點為點雙連通分量最高的結點,而 d n dn dn 結點為點雙連通分量最低的結點),而對應到圓方樹里面,發現 3 3 3 就是其父親!

整理一下可得:

新性質:圓方樹里方點的父親恰好是深搜樹中其對應的點雙里最高的點。


考慮另一件事情:如何處理環上兩點之間的最短距離。

不妨在圓方樹里面,針對 14 14 14 號方點進行舉例,即原深搜樹中的綠色點雙連通分量的部分。后面的抽象文字如果有不懂的可以對照著圖片想想為什么。

因為獲取距離的方法較為套路,這里就簡要講講思考在這個方法的過程。

發現一個環一定是一條鏈加上一條回邊,這是不由分說地。而且還可以發現兩點之間的距離要么是在這條構成環的鏈上的距離(也就是直接從深度小的點通過走鏈走到深度大的點),要么是從另一個方向過來的距離(也就是先從深度小的點走到 u p up up,然后再走 d n dn dn,再有 d n dn dn 走到深度較大的點)

顯然兩點之間的最短距離就是上面兩片粗體字得到答案的 min ? \min min 值。但是這兩個答案太難算了,有沒有一些突破口呢?

顯然是有的,因為我們可以發現第一托路徑的答案 + + + 第二托路徑的答案 = = = 整個環的路徑權值和。

那么就可以通過路徑權值和來快速通過前者得到后者。而且路徑權值和是一個定值,因為其他地方沒地方放了,就直接把環里面的路徑權值和作為這個環對應的方點的點權即可。

而對于前面提到的第一托可能的路徑,可以使用在鏈上 u p up up 到這個點的距離來記錄。這樣就做完了。最終還有每一個方點到其 u p up up 的距離設為 0 0 0

總結一下:

  • 方點到其 u p up up 的邊權設為 0 0 0

  • 圓點到方點的邊權,設為在深搜樹中方點的 u p up up 到圓點的鏈上距離。

  • 將方點的點權設為環內所有邊權的總和。

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

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

相關文章

華為OD機試真題——洞穴探險(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳實現

2025 A卷 200分 題型 本專欄內全部題目均提供Java、python、JavaScript、C、C++、GO六種語言的最佳實現方式; 并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析; 本文收錄于專欄:《2025華為OD真題目錄+全流程解析+備考攻略+經驗分…

Java設計模式之職責鏈模式詳解

Java設計模式之職責鏈模式詳解 一、職責鏈模式核心思想 核心目標&#xff1a;將請求的發送者與接收者解耦&#xff0c;使多個對象都有機會處理請求。這些處理者形成鏈式結構&#xff0c;請求沿鏈傳遞直到被處理或到達鏈尾&#xff0c;如政府審批層層上報機制。 二、職責鏈模式…

解決WPF短暫的白色閃爍(白色閃屏)

在 WPF 應用程序啟動時出現 短暫的白色閃爍&#xff08;白色閃屏&#xff09;&#xff0c;通常是由于以下原因導致的&#xff1a; 主要原因 WPF 默認窗口背景是白色&#xff0c;在加載 UI 之前會短暫顯示白色背景。 解決方案 設置窗口背景為透明或黑色&#xff08;推薦&…

《Python基礎》第1期:人生苦短,我用Python

介紹 Python 在英語中是蟒蛇的意思&#xff0c;它的 logo 也是兩條蟒蛇纏繞在一起。 然而 Python 和蟒蛇實際上沒有半點關系。 Python 是由荷蘭程序員 Guido van Rossum&#xff08;因為其名字的前三個字母“gui”是中文“龜”的拼音&#xff0c;所以江湖人稱“龜叔”&#x…

DiT、 U-Net 與自回歸模型的優勢

DiT 相對于 U-Net 的優勢 全局自注意力 vs. 局部卷積 U-Net 依賴卷積和池化/上采樣來逐層擴大感受野&#xff0c;捕捉全局信息需要堆疊很多層或借助跳躍連接&#xff08;skip connections&#xff09;。DiT 在每個分辨率階段都用 Transformer 模塊&#xff08;多頭自注意力 ML…

怎么查找idea插件的下載位置,并更改

長期使用 IntelliJ IDEA 時&#xff0c;默認存儲在 C 盤的配置文件會持續生成大量緩存和日志文件&#xff0c;可能導致系統盤空間不足。通過修改默認配置文件存儲位置&#xff0c;可以有效釋放 C 盤空間并提升系統性能。 1&#xff0c;先找到自己idea的下載目錄&#xff0c;再打…

IoT/HCIP實驗-1/物聯網開發平臺實驗Part2(HCIP-IoT實驗手冊版)

文章目錄 概述產品和設備實例的產品和設備產品和設備的關聯單個產品有多個設備為產品創建多個設備產品模型和物模型設備影子&#xff08;遠程代理&#xff09; 新建產品模型定義編解碼插件開發編解碼插件工作原理消息類型與二進制碼流添加消息&#xff08;數據上報消息&#xf…

15.進程間通信(一)

一、進程間通信介紹 進程間通信目的&#xff1a; 數據傳輸&#xff1a;一個進程需要將它的數據發送給另?個進程 資源共享&#xff1a;多個進程之間共享同樣的資源。 通知事件&#xff1a;一個進程需要向另一個或一組進程發送消息&#xff0c;通知它&#xff08;它們&#xf…

05-jenkins學習之旅-vue前項目部署實踐

1、創建被管理項目 2、構建流程說明 jenkins其實就是將服務部署拆分成了&#xff1a; 1、拉取代碼(git) 2、打包編譯(npm install) 3、自定義腳本(dist復制、執行啟動腳本) 4、部署成功后的一些通知等 3、demo配置 3.1、General 3.2 源碼管理 添加用戶名密碼方式如下圖 3.2…

服務器中分布式存儲數據技術都包含哪些內容?

隨著大數據時代的到來&#xff0c;企業和組織對于服務器的存儲要求也在不斷地增高&#xff0c;傳統的存儲架構已經無法滿足一些大規模的數據存儲和處理需求&#xff0c;分布式存儲技術應運而生&#xff0c;成為了大數據存儲的重要基礎設施&#xff0c;下面&#xff0c;就來介紹…

從比分滾動到數據革命:體育數據如何重構我們的觀賽體驗?

當凌晨三點的歐冠決賽與鬧鐘沖突時&#xff0c;當世界杯小組賽因時差難以全程跟進時&#xff0c;當代體育迷早已不再依賴電視直播 —— 打開手機里的比分網&#xff0c;實時跳動的體育大數據正構建著全新的觀賽宇宙。這些曾經被視為 "輔助工具" 的平臺&#xff0c;如…

vue2使用element中多選組件el-checkbox-group,數據與UI更新不同步

問題描述 使用element多選checkbox組件&#xff0c;點擊勾選取消勾選&#xff0c;視圖未變化&#xff0c;再次點擊表單其他元素&#xff0c;多選組件勾選狀態發生變化&#xff0c;視圖和數據未同步 第一次嘗試&#xff1a;再el-checkbox-group多選父組件上增加點擊事件&…

CodeTop之LRU緩存

題目鏈接 146. LRU 緩存 - 力扣&#xff08;LeetCode&#xff09; 題目解析 算法原理 我們使用雙向鏈表哈希表的形式來模擬緩存機制 首先我們要自己實現一個雙鏈表, 自己寫一個內部類, 這個內部類記錄了key,value,prev,next(前驅和后繼), 后續我們就通過這個內部類來構造雙…

PyQt學習系列11-綜合項目:多語言文件管理器

PyQt學習系列筆記&#xff08;Python Qt框架&#xff09; 第十一課&#xff1a;綜合項目 - 多語言文件管理器 &#xff08;原課程規劃中的第十五課&#xff0c;按用戶要求調整為第十一課&#xff09; 課程目標 綜合運用PyQt框架開發一個支持多語言的文件管理器實現以下核心功…

【Ubuntu修改串口延時(Latency Timer)為1毫秒(設備拔插或系統重啟后自動生效)】

Ubuntu修改串口延時Latency Timer為1毫秒-設備拔插或系統重啟后自動生效 在Ubuntu系統中&#xff0c;串口設備的延時參數(latency_timer)可以通過udev規則永久修改。以下是完整步驟&#xff1a; 創建udev規則文件 sudo vim /etc/udev/rules.d/99-ftdi-low-latency.rules添加以…

OpenCV CUDA模塊圖像處理------顏色空間處理之GPU 上交換圖像的通道順序函數swapChannels()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 該函數用于在 GPU 上交換圖像的通道順序&#xff08;例如將 BGR 圖像轉為 RGB&#xff09;。 它適用于多通道圖像&#xff08;如 3 通道或 4 通道…

Linux Ubuntu24.04配置安裝MySQL8.4.5高可用集群主從復制!

MySQL 主從復制&#xff08;Replication&#xff09;是實現數據高可用、讀寫分離及異地容災的核心機制之一。主庫寫、從庫讀&#xff0c;提升并發能力&#xff1b;讀寫分離&#xff0c;減輕主庫壓力。 本地 windows 系統有一個Linux Ubuntu子系統&#xff0c;版本為Ubuntu 24.…

R基于邏輯回歸模型實現心臟病檢測及SHAP值解釋項目實戰

說明&#xff1a;這是一個機器學習實戰項目&#xff08;附帶數據代碼文檔視頻講解&#xff09;&#xff0c;如需數據代碼文檔視頻講解可以直接到文章最后關注獲取。 1.項目背景 心血管疾病是全球范圍內導致死亡的主要原因之一&#xff0c;每年有數百萬人因此失去生命。在眾多的…

嵌入式學習筆記 -函數嵌套時以及異常響應時,LR使用的具體過程

函數嵌套時以及異常響應時&#xff0c;寄存器LR的作用存在顯著區別&#xff0c;理解這個問題對于理解freeRTOS底層代碼的實現大有幫助&#xff0c;具體使用過程如下&#xff1a; 一 函數嵌套時的LR使用的具體過程 在ARM架構(特別是M0處理器)中&#xff0c;函數嵌套調用時LR(L…

Java String函數的使用

文章目錄 String字符串比較字符串查找轉化字符串替換字符串拆分字符串截取&#xff08;常用&#xff09;字符串的不可變性 String str本來是字符串常量的引用&#xff0c;應該打印地址&#xff0c;但是編譯器重寫了toString方法&#xff0c;所以打印hello String 的構造方法 …