無向圖全域性最小邊割集
可以用最小切割最大流定理:
1.min=MAXINT,確定一個源點
2.列舉匯點
3.計算最大流,並確定當前源匯的最小割集,若比min小更新min
4.轉到2直到列舉完畢
5.min即為所求輸出min
不難看出複雜度很高:列舉匯點要O(n),最短增廣路最大流演算法求最大流是O((n^2)m)複雜度,在複雜網路中O(m)=O(n^2),演算法總複雜度就是O(n^5);哪怕採用最高標號預進流演算法求最大流O((n^2)(m^0.5)),演算法總複雜度也要O(n^4)
所以用網路流演算法求解最小割集複雜度不會低於O(n^4)。
---------
prim演算法不僅僅可以求最小生成樹,也可以求“最大生成樹”。最小割集Stoer-Wagner演算法就是典型的應用例項。
求解最小割集普遍採用Stoer-Wagner演算法,不提供此演算法證明和程式碼,只提供演算法思路:
1.min=MAXINT,固定一個頂點P
2.從點P用“類似”prim的s演算法擴展出“最大生成樹”,記錄最後擴充套件的頂點和最後擴充套件的邊
3.計算最後擴充套件到的頂點的切割值(即與此頂點相連的所有邊權和),若比min小更新min
4.合併最後擴充套件的那條邊的兩個端點為一個頂點(當然他們的邊也要合併,這個好理解吧?)
5.轉到2,合併N-1次後結束
6.min即為所求,輸出min
prim本身複雜度是O(n^2),合併n-1次,演算法複雜度即為O(n^3)
如果在prim中加堆優化,複雜度會降為O((n^2)logn)
這個Stoer-Wagner演算法可以參見這篇paper(http://docs.google.com/fileview?id=0BwxLvD9mcDNtMjk3MWVkMTAtZjMzNi00ZWE3LTkxYjQtYTQwNzcyZTk3Njk2&hl=en), 其核心思想是迭代縮小規模, 演算法基於這樣一個事實:
對於圖中任意兩點s和t, 它們要麼屬於最小割的兩個不同集中, 要麼屬於同一個集.
如果是後者, 那麼合併s和t後並不影響最小割. 基於這麼個思想, 如果每次能求出圖中某兩點之間的最小割, 然後更新答案後合併它們再繼續求最小割, 就得到最終答案了. 演算法步驟如下:
1. 設最小割cut=INF, 任選一個點s到集合A中, 定義W(A, p)為A中的所有點到A外一點p的權總和.
2. 對剛才選定的s, 更新W(A,p)(該值遞增).
3. 選出A外一點p, 且W(A,p)最大的作為新的s, 若A!=G(V), 則繼續2.
4. 把最後進入A的兩點記為s和t, 用W(A,t)更新cut.
5. 新建頂點u, 邊權w(u, v)=w(s, v)+w(t, v), 刪除頂點s和t, 以及與它們相連的邊.
6. 若|V|!=1則繼續1.
看起來很簡單, 每次像做最大生成樹一樣選最大"邊"(注意, 這裡其實不是邊, 而是已經累計的權值之和, 就當是加權的度好了), 然後把最後進入的兩個點縮到一塊就可以了. 合併點最多有n-1次, 而不加堆優化的prim是O(n^2)的, 所以最終複雜度O(n^3), 要是你有心情敲一大坨程式碼, 還可以在稀疏圖上用Fibonacci Heap優化一下, 不過網上轉了一圈, 大多都是說能用Fibonacci Heap優化到怎樣怎樣的複雜度, 真正能自己寫出來的恐怕也沒幾個, 看看uoregon(俄勒岡大學)的一大坨程式碼就有點寒. (http://resnet.uoregon.edu/~gurney_j/jmpc/fib.html)
特別注意幾個地方, 網上的好幾個Stoer-Wagner版本都存在一些小錯誤:
1. 演算法在做"最大生成樹"時更新的不是普通意義上的最大邊, 而是與之相連的邊的權值和, 當所有邊都是單位權值時就是累計度.
2. "最後進入A的兩點記為s和t", 網上對s有兩種解釋, 一是在t之前一個加進去的點, 二是t的前趨節點, 也就是最後選擇的那條邊的另一端. 正解是第一種!
3. 對於稠密圖, 比如這題, 我用堆, 對映二分堆, 或者STL的優先佇列都會TLE, 還不如老老實實O(n^3).
1#include <iostream> 2#include <cmath> 3usingnamespace std;
4int mat[600][600];
5int res;
6//Stoer-Wagner演算法,加了自己看得懂的備註
7//無向圖全域性最小割,用求prim類似方法o(n^3),學習了一個下午……
8//一開始用列舉源點匯點的最大流求解,複雜度o(n^5) 超時 9int min(int a,int b)
10{
11 if(a<b) return a;
12 elsereturn b;
13}14
15void Mincut(int n)
16{
17 int node[600], dist[600];
18 bool visit[600];
19 int i, prev, j, k;
20 for (i =0; i < n; i++)
21 node[i] = i;
22 while (n >1)
23 {
24 int maxj =1;
25 for (i =1; i <n; i++) //初始化到已圈集合的割大小26{
27 dist[node[i]] = mat[node[0]][node[i]];
28 if (dist[node[i]] > dist[node[maxj]])
29 maxj = i;
30 }31 prev =0;
32 memset(visit, false, sizeof (visit));
33 visit[node[0]] =true;
34 for (i =1; i < n; i++)
35 {
36 if (i == n -1)//只剩最後一個沒加入集合的點,更新最小割37{
38 res = min(res, dist[node[maxj]]);
39 for (k =0; k < n; k++) //合併最後一個點以及推出它的集合中的點40{
41 mat[node[k]][node[prev]]=(mat[node[prev]][node[k]]+=mat[node[k]][node[maxj]]);
42 }43 node[maxj] = node[--n]; //縮點後的圖44 }45 visit[node[maxj]] =true;
46 prev = maxj;
47 maxj =-1;
48 for (j =1; j < n; j++)
49 {
50 if (!visit[node[j]]) //將上次求的maxj加入集合,合併與它相鄰的邊到割集51{
52 dist[node[j]] += mat[node[prev]][node[j]];
53 if (maxj ==-1|| dist[node[maxj]] < dist[node[j]])
54 maxj = j;
55 }56 }57 }58
59 }60 return;
61}62
63int main()
64 {
65 int n, m, a, b, v;
66 while (scanf("%d%d", &n, &m) != EOF)
67 {
68 res = (1<<29);
69 memset(mat, 0, sizeof (mat));
70 while (m--)
71 {
72 scanf("%d%d%d", &a, &b, &v);
73 mat[a][b] += v;
74 mat[b][a] += v;
75 }76 Mincut(n);
77 printf("%d\n", res);
78 }79 return0;
80}81
相關推薦
無向圖全域性最小邊割集
一個無向連通網路,去掉一個邊集可以使其變成兩個連通分量則這個邊集就是割集;最小割集當然就權和最小的割集。 可以用最小切割最大流定理: 1.min=MAXINT,確定一個源點 2.列舉匯點 3.計算最大流,並確定當前源匯的最小割集,若比min小更新min 4.轉到2直到列舉完畢 5.min即為所求輸出min
hdu 1599 find the mincost route 無向圖的最小環 求從一個點遍歷所有節點以後回到原點的最短
在寫題解之前給自己打一下廣告哈~。。抱歉了,希望大家多多支援我在CSDN的視訊課程,地址如下:http://edu.csdn.net/course/detail/209題目:find the mincost routeTime Limit: 1000/2000 MS (Java
hdu1599 【無向圖的最小環】
杭州有N個景區,景區之間有一些雙向的路來連線,現在8600想找一條旅遊路線,這個路線從A點出發並且最後回到A點,假設經過的路線為V1,V2,....VK,V1,那麼必須滿足K>2,就是說至除了出發點以外至少要經過2個其他不同的景區,而且不能重複經過同一個景區。現在860
Beehives 找無向圖的最小環..BFS..
題意: 給了一個無向圖(至多700個點,兩點間無重邊),問其中邊數最少的環是所少條邊 題解: 這類問
SSL-1763 觀光旅遊(求無向圖的最小環問題)
目錄 題面 Description 在桑給巴爾島的Adelton城鎮上有一個旅遊機構。它們決定在提供許多的其它吸引之外,再向客人們提供旅遊本鎮的服務。 為了從提供的吸引服務中儘可能地獲利,這個旅遊機構接收了一個精明決定:在相同的起點與終點之間找出
無向圖最小點割集解法
from: http://www.cppblog.com/imky/archive/2010/08/14/123414.html 無向圖最小點割集,確定起點S,終點T。每個點都有自己的點權值vi,求最小點權和的割點集,使得S無法到達T。 解法:將每個點拆分為兩個點v和v',
HDU1845Jimmy’s Assignment(無向圖,最大匹配)
comment 最大匹配 tex dfs asc ddc repr freopen ces 題意:就是求最大匹配 #include<cstdio> #include<iostream> #include<algorit
HDU - 6311 Cover(無向圖的最少路徑邊覆蓋 歐拉路徑)
algorithm 奇數 detail cos log csdn puts true its 題意 給個無向圖,無重邊和自環,問最少需要多少路徑把邊覆蓋了。並輸出相應路徑 分析 首先聯通塊之間是獨立的,對於一個聯通塊內,最少路徑覆蓋就是 max(1,度數為奇數點的個
[Data Structure & Algrithom] 無向圖的最小生成樹
kruskal算法 如果 data spa amp imu 數據 結點 實現 最小生成樹(Minimum Spanning Tree) - 連接所有頂點的邊的權值之和最小的樹 Prim算法 基本思路 - 設 圖的頂點集合為V;其最小生成樹的頂點集合為U 將某個頂點放入U
鏢局運鏢---無向圖的最小生成樹
假設有n個城市和m條道路,對應無向圖中的點和邊。每條路的過路費對應邊的權值。鏢局現在需要選擇一些道路進行疏通,以便邊距可以達到任意一個城鎮,要求花費的銀子越少越好。換句話說,鏢局的要求就是用最少的邊讓圖連通(任意兩點之間可以互相到達),將多餘的邊去掉。 很顯然,要想
無向圖求最短路徑 迪傑斯特拉(dijkstra)演算法實現
Dijkstra演算法說明 http://ibupu.link/?id=29namespace ConsoleApp14 { class Program { public static int M = -1; static
怎麼證明權重不相同的加權無向圖的最小生成樹是唯一的 (圖論)
設G是所有邊權均不相同的無向聯通圖。 證明一: 首先,易證圖G中權值最小的邊一定是最小生成樹中的邊。(否則最小生成樹加上權值最小的邊後構成一個環,去掉環中任意一條非此邊則形成了另一個權值更小的生
無向圖的最短路徑求解演算法之——Dijkstra演算法【轉】
在準備ACM比賽的過程中,研究了圖論中一些演算法。首先研究的便是最短路的問題。《離散數學》第四版(清華大學出版社)一書中講解的Dijkstra演算法是我首先研究的源材料。 如何求圖中V0到V5的最短路徑呢? java實現的方式如下:
用Dijkstra演算法求解無向圖的最短路徑
Dijkstra演算法是典型的演算法。Dijkstra演算法是很有代表性的演算法。Dijkstra一般的表述通常有兩種方式,一種用永久和臨時標號方式,一種是用OPEN, CLOSE表的方式,這裡均採用永久和臨時標號的方式。注意該演算法要求圖中不存在負權邊。
迪傑斯特拉演算法處理無向圖中最短路徑的(dijkstra)Java實現(指定兩點,求最短距離及路徑)
其實不是原創哈,我寫不出來。 如何求圖中V0到V5的最短路徑呢? java實現的方式如下: 第一步,根據圖來建立權值矩陣: int[][] W = { { 0, 1, 4, -1, -
Tarjan無向圖縮環(求邊雙)/有向圖縮環(求邊雙)/無向圖求點雙
邊雙與點雙 不嚴謹的定義, 邊雙=刪掉一條邊依然連通 點雙=刪掉一個點依然連通 無向圖Tarjan求邊雙 先說無向圖。無向圖就比有向圖簡單一些,因為只有返祖邊而沒有橫叉邊。 用棧來儲存已訪問的點。 如果已經訪問過了,就把它當返祖邊處理(low=min(low,
The Unique MST——判斷一個連通無向圖的最小生成樹是否是唯一的
Think: 1知識點:判斷一個連通無向圖的最小生成樹是否是唯一的+最小生成樹_Prim演算法+記錄路徑 2題意:給定一個連通無向圖,判斷這個連通無向圖的最小生成樹是否是唯一的 3錯誤反思: 4思路: 1>思路1:第一遍Prim演算法求出路徑最小
每日一省之————加權無向圖的最小生成樹演算法(Prim/Kruskal演算法)
1.帶權重的邊的資料結構 /** * 該類物件可以表示圖中的一條邊 * @author lhever 2017年2月19日 下午5:10:49 * @version v1.0 */ public class Edge implements Com
poj 1734 Floyd算求有向圖的最小環
題意:旅遊公司要開發一條新的路線 , 要求這是一個總路程儘可能短的環 , 並且不能只含兩個城市 , 除開起點外 , 不能重複走之前走過的城市 , 輸出這條路線? Floyd演算法求最小環 程式碼: //用floyd演算法 , 求有向圖的最小環 #include #include #include #i
怎麽證明權重不相同的加權無向圖的最小生成樹是唯一的 (圖論)
少包 size tail ati color post 中一 pos 否則 轉自:https://blog.csdn.net/liangzhaoyang1/article/details/51602926 設G是所有邊權均不相同的無向聯通圖。 證