考慮如下問題:
乙個牧場由r*c個點組成。牧場內有若干條運輸通道,通道流量上限是ci,連線水平或者垂直相鄰的的點。(1,1)內有很多乾草,farmer john希望將乾草運送到點(r,c)。問最大流量是多少。1
一種直觀的解法:
將每個站點看成點,相鄰的點之間有邊,流量上限為ci。將(1,1)作為源,(r,c)作為匯,求最大流即可。
是否可行?
上述解法,點數最多為40000,邊數最大為80000。用最大流sap求解複雜度為(n*n*m),顯然不合理。
分析:
題目給出的是乙個平面圖,並且s和t都在圖中無邊介面的邊界上。在這裡,我們稱之為s-t平面圖。同時利用對偶圖(面f-->點f*,邊屬於兩個面f1、f2,有點(f1*,f2*))和原圖的關係,轉化為最短路徑求解。
具體步驟:
首先連一條邊(s,t),它將無邊介面分解為2個面。求該圖的對偶圖g*,設無邊介面為點t*,附加面為點s*。刪去邊(s*,t*)。這樣,s*到t*的任意一條路徑就對應了原圖的乙個割,顯然,最短路徑即為最小割。
例:hdu3870
題意:**。給乙個n*n的格仔,求從(1,1)到(n,n)的最大流。
解:同上。
/*
s-t平面圖最小割轉最短路徑
建模:1.在原圖中新增一條從s到t的邊,得到乙個附加面,變為圖g。
2.求圖g的對偶圖g*:
g的面i-->g*的點i,g的一條邊若屬於兩個平面i,j,g*中連邊(i,j,w)。另附加面為點s*,無介面為t*。
(g和g*的關係:面數=點數,點數=面數,邊數=邊數)
3.s*到t*的任意一條路徑對應原圖的乙個割。求最短路徑即可。
*/#include #include #include #include using namespace std;
const int inf = 0x3f3f3f3f;
const int maxv = 400*400+10; //原圖中最大的面數 = 2*n*(n-1)-n*n+2=(n-1)^2 + 1。
int mx[405][405];
struct edge
e[6*maxv];
int head[maxv],edgenum;
bool vis[maxv];
int dis[maxv];
void addedge(int from, int to, int w)
int spfa(int start, int end)}}
}return dis[end];
}int main()
if(i < n-1)}}
for(j = 1; j < n; j++)
for(i = 1; i < n; i++)
printf("%d\n",spfa(start,end));
}return 0;
}
hdu 6582 最短路 最小割)
打完比賽,請教大佬,大佬口胡講解。於是有了下面的 邊權和超過int,wa了兩發 include using namespace std 優化解釋的 const int n 20000 const int inf 0x7fffffff const long long inf 0x7ffffffffff...
BZOJ 1001 最短路求最小割
對於這道題,是乙個裸的求一張圖最小割的問題,可是資料太大,dinic過不了,注意到題目中的圖是平面圖,因此我們可以通過將平面圖轉化為對偶圖的形式在對偶圖中跑最短路,這樣就可以用spfa或堆優化的dijkstra來做了 include include include includeusing name...
hdu 6582 path 最短路 最小割
題意 有n個點,m條單向帶權邊,起點為1,終點為n,如果開始沒有最短路輸出0,現在想堵住一些路,使堵之後的最短路值變大,或不存在。堵路的花費就是邊的權值,問最小花費。思路 找到最短路核心邊,再重新建邊,跑一遍最小割即可。找最短路核心邊要正向建邊找每點到起點的距離 假設為d i 再反向建邊找每點到終點...