洛谷P2764 最小路徑覆蓋問題

2021-09-24 09:10:53 字數 1765 閱讀 5655

剛一看到這道題十分的懵,完全不知道從何下手

然後看了看題解後發現,這道題的關鍵就是計算可以合併多少次路徑,然後最小的路徑覆蓋數就是總點數-合併次數。

舉個例子:(僅僅是讓你理解上面一句話,而不一定是真正的**執行流程)

初始:

合併1次:

合併2次:

合併3次:

所以最後最小路徑覆蓋數即為:5-3=2

(注意:1、4號點之間不能合併,因為路徑是鏈狀的,這說明了很重要的一點:每乙個點都最多只能合併其它點一次,被合併一次,這正是之後在建網路時要把源點到x的邊和x'到匯點的邊的容量賦值為1的原因)

通過思考再看一看題解,我們發現:

可以先把每個點拆開,其中乙個代表由這個點為起點(x),另乙個代表由這個點為終點(x')。

然後在源點(s)與每乙個x之間連一條容量為1的邊,在每乙個x'與匯點(t)之間連一條容量為1的邊。

最後對於每乙個輸入的邊(x,y),我們都在x與y'之間連一條容量為inf的邊。

tips:一定不要忘加反向邊!一定不要忘加反向邊!一定不要忘加反向邊!(因為介個我調了好久qaq)

那麼如果有一條路徑s-x-y'-t的流量為1,那就說明將x所代表的點與y'所代表的點合併。

所以在我們跑完一遍最大流之後,得到的最大流量就是合併次數。

最小的路徑覆蓋數(答案)就是總點數-合併次數。

#include#include#include#define maxn 1010

#define maxm 100010

#define inf 0x3f3f3f3f

using namespace std;

int bg[maxn],nt[maxm],to[maxm],w[maxm],e=1;

int q[maxn<<2],dep[maxn],n,m,s,t,ans,nxt[maxn],pre[maxn];

void insert(int x,int y,int z)

int bfs()

}return dep[t];

}int dfs(int x,int s)

}return res;

}int dinic()

return res;

}int main()

for (i=1;i<=m;i++)

ans=n-dinic();

for (i=2;i<=e;i+=2)

if (n對了,講一下我的方案輸出方法:(利用雙向鍊錶維護)

在跑玩dinic後掃一下每一條(正向)邊(構造的網路邊),如果這條邊連線著兩個非源非匯的點(x,y)且它的反向邊不為0(即這條邊被流過),就使pre[y]=x; nxt[x]=y;

最後輸出時就看當前點的前驅是否為0,若是,其就為一條路徑的起始點,從它開始一直遍歷其後繼並輸出,直到跑完為止

tips:一定要注意細節,比如x'在變回原來的點時要-n

完結散花qwq

洛谷P2764 最小路徑覆蓋

給定有向圖 g v,e 設 p 是 g 的乙個簡單路 頂點不相交 的集合。如果 v 中每個定點恰好在p的一條路上,則稱 p 是 g 的乙個路徑覆蓋。p中路徑可以從 v 的任何乙個定點開始,長度也是任意的,特別地,可以為 0 g 的最小路徑覆蓋是 g 所含路徑條數最少的路徑覆蓋。設計乙個有效演算法求乙...

P2764 最小路徑覆蓋問題

我做24題的第六題,輸出路徑還是有點糊塗 給定有向圖g v,e 設p是圖g上若干點不相交的簡單路徑的集合,若每個點v屬於v都存在於唯一一條p中的路徑上,則p是g的一條路徑覆蓋。路徑數量最少的路徑覆蓋稱為最小路徑覆蓋。用minpc g 表示圖g的最小路徑覆蓋數.有向無環圖的最小路徑覆蓋問題可轉化為二分...

P2764 最小路徑覆蓋問題

問題描述 每條邊的容量均為1。求網路g1的 0 x 0 y 最大流。程式設計任務 對於給定的給定有向無環圖g,程式設計找出g的乙個最小路徑覆蓋。輸入格式 件第1 行有2個正整數n和m。n是給定有向無環圖g 的頂點數,m是g 的邊數。接下來的m行,每行有2 個正整數i和j,表示一條有向邊 i,j 輸出...