P2764 最小路徑覆蓋問題 網路流 題之一

2022-03-04 22:00:04 字數 3266 閱讀 3895

«問題描述:

每條邊的容量均為1。求網路g1的( 0 x , 0 y )最大流。

«程式設計任務:

對於給定的給定有向無環圖g,程式設計找出g的乙個最小路徑覆蓋。

輸入格式:

件第1 行有2個正整數n和m。n是給定有向無環圖g 的頂點數,m是g 的邊數。接下來的m行,每行有2 個正整數i和j,表示一條有向邊(i,j)。

輸出格式:

從第1 行開始,每行輸出一條路徑。檔案的最後一行是最少路徑數。

輸入樣例#1: 

11 12

1 21 3

1 42 5

3 64 7

5 86 9

7 10

8 11

9 11

10 11

輸出樣例#1: 

1 4 7 10 11

2 5 8

3 6 9

3

1<=n<=150,1<=m<=6000

由@zhouyonglong提供spj

solution:

先簡單的解釋一下最小路徑覆蓋:大致就是在乙個有向無環圖中,用最少多少條簡單路徑能將所有的點覆蓋(簡單路徑簡單來說就是一條路徑不能和其他路徑有重複的點,當然也可以認為單個點是一條簡單路徑)。

仔細思考,容易發現有些類似於二分圖匹配的問題,異曲同工。

演算法:把原圖的每個點v拆成v

x'>vx和vy

'>vy

兩個點,如果有一條有向邊a->b,那麼就加邊ax−

>by

'>ax−>by

。這樣就得到了乙個二分圖。那麼最小路徑覆蓋=原圖的結點數-新圖的最大匹配數。

證明:一開始每個點都是獨立的為一條路徑,總共有n條不相交路徑。我們每次在二分圖里找一條匹配邊就相當於把兩條路徑合成了一條路徑,也就相當於路徑數減少了1。所以找到了幾條匹配邊,路徑數就減少了多少。所以有最小路徑覆蓋=原圖的結點數-新圖的最大匹配數。

因為路徑之間不能有公共點,所以加的邊之間也不能有公共點,這就是匹配的定義。

方法一:二分圖匹配。綜合上述所說的,我們可以直接建圖,然後跑匈牙利演算法,輸出的話只需將所匹配的點依次輸出就ok了。

**(copy乙份):

1 #include 2

using

namespace

std;

3 typedef long

long

ll;

4const

int maxn = 305

; 5

const

int maxm = 20005

; 6

struct

edge

7e[maxm], *h[maxn], *edges;

11int

res[maxn];

12int

vis[maxn];

13void addedges(int u, int

v)

14

19void

init()

20

25bool find(int

u)

26

34}

35return

false

; 36

} 37

intn, m;

38 vectorans;

39int

to[maxn];

40void

work() 41

47int result = 0

; 48

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

52 memset(to, 0, sizeof

to);

53for(int i = 1; i <= n; i++) if(res[i] != -1) to[res[i]] =i;

54for(int i = 1; i <= n; i++) if(res[i] == -1

)

62for(int j = 0; j < ans.size(); j++) printf("

%d%c

", ans[j], j == ans.size() - 1 ? '

\n' : '

');

63}

64 printf("

%d\n

", n -result);

65}

66int

main()

67

方法二:網路最大流。這裡的做法和二分圖匹配用最大流的做法是一樣的。附加炒雞源s和炒雞匯t,然後建圖(邊權為1),最後跑最大流,輸出時方法很多,我選擇的是從匯點按殘餘流量的有無來往前找一條路徑並遞迴輸出。

**(手打dinic):

1 #include2

#define il inline

3using

namespace

std;

4const

int n=1000,inf=23333333;5

int n,m,s,t=520,h[n],dis[n],cnt=1

,fa[n];

6struct

edgee[100005

];9 il void add(int u,int v,int

w)10

14 queueq;

15 il bool

bfs()

1625

return dis[t]!=-1;26

}27 il int dfs(int u,int

op)2843}

44if(!flow)dis[u]=-1;45

return

flow;46}

47 il void print(int

x)48

54int

main()

5565

int ans=n;

66while(bfs())ans-=dfs(s,inf);

67for(int i=h[t];i;i=e[i].net)

6872 printf("%d"

,ans);

73return0;

74 }

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 輸出...

P2764 最小路徑覆蓋問題

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