網路流24題 最小路徑覆蓋問題

2021-08-26 23:46:07 字數 1606 閱讀 8645

有向無環圖最小路徑覆蓋,可以轉化成二分圖最大匹配問題,從而用最大流解決。

構造二分圖,把原圖每個頂點i拆分成二分圖x,y集合中的兩個頂點xi和yi。對於原圖中存在的每條邊(i,j),在二分圖中連線邊(xi,yj)。然後把二分圖最大匹配模型轉化為網路流模型,求網路最大流。

最小路徑覆蓋的條數,就是原圖頂點數,減去二分圖最大匹配數。沿著匹配邊查詢,就是乙個路徑上的點,輸出所有路徑即可。

對於乙個路徑覆蓋,有如下性質:

1、每個頂點屬於且只屬於乙個路徑。

2、路徑上除終點外,從每個頂點出發只有一條邊指向路徑上的另一頂點。

所以我們可以把每個頂點理解成兩個頂點,乙個是出發,乙個是目標,建立二分圖模型。該二分圖的任何乙個匹配方案,都對應了乙個路徑覆蓋方案。如果匹配數為0,那麼顯然路徑數=頂點數。每增加一條匹配邊,那麼路徑覆蓋數就減少乙個,所以路徑數=頂點數 - 匹配數。要想使路徑數最少,則應最大化匹配數,所以要求二分圖的最大匹配。

注意,此建模方法求最小路徑覆蓋僅適用於有向無環圖,如果有環或是無向圖,那麼有可能求出的一些環覆蓋,而不是路徑覆蓋。

#include using namespace std;

const int maxn = 1000;

const int maxm = 50000;

const int inf = 0x3f3f3f3f;

struct edge1

;struct dinic

edges.clear();

} void addedge(int from,int to,int cap)

); edges.push_back((edge1));

m = edges.size();

g[from].push_back(m - 2);

g[to].push_back(m - 1);

} bool bfs()

}} return vis[t];

} int dfs(int x,int a)

}return flow;

} int maxflow(int s,int t)

return flow;

}}din;

int to[500];

bool vis[500];

int main(void)

for(int i = 1; i <= n; i++) din.addedge(i + n,t,1);

int ans = n - din.maxflow(s,t);

memset(to,0,sizeof(to));

memset(vis,false,sizeof(vis));

for(int i = 0; i < din.edges.size(); i++)

}for(int i = 1; i <= n; i++)

printf("\n");}}

printf("%d\n",ans);

return 0;}/*

11 12

1 21 3

1 42 5

3 64 7

5 86 9

7 10

8 11

9 11

10 11

*/

網路流24題 最小路徑覆蓋 (最小路徑覆蓋)

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

最小路徑覆蓋問題(網路流24題)

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

網路流24題 最小路徑覆蓋問題

p2764 傳送門 基本模型 首先結論為 將每個點 v 拆成 v,v 有向邊 edge u,v 改為 edge u,v 建成二分圖 那麼 最小路徑覆蓋數 n 二分圖最大匹配數 證明 匹配 u,v 相當於連線了 u,v 連通塊個數減一,想要連通塊最少自然要最大匹配 如果要輸出方案的話增廣時記錄 u 的...