當前位置:
首頁 >
LA 6474 Drop Zone (最小割)
發布時間:2025/4/16
44
豆豆
生活随笔
收集整理的這篇文章主要介紹了
LA 6474 Drop Zone (最小割)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
要添最少的擋板使所有的'D'不存在到達網格外的路徑.
? ? ? 以每個格子向四個方向中可以到達的格子連容量為1的邊, 從源點向所有'D' 連容量為4的邊,網格外的點向匯點連一條容量為4的邊.
? ? ? 答案就是這個容量網絡的最小割,即最大流.
?
/*最大流SAP鄰接表思路:基本源于FF方法,給每個頂點設定層次標號,和允許弧。優化:1、當前弧優化(重要)。1、每找到以條增廣路回退到斷點(常數優化)。2、層次出現斷層,無法得到新流(重要)。時間復雜度(m*n^2) */ #include <iostream> #include <cstdio> #include <cstring> #include <utility> #include <vector> #define ms(a,b) memset(a,b,sizeof a) using namespace std; const int INF = 6111; struct node {int v, c, next; } edge[100000]; int pHead[100000], SS, ST, nCnt; int n, m; int g[200][200]; int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; //同時添加弧和反向邊, 反向邊初始容量為0 void addEdge (int u, int v, int c) {edge[++nCnt].v = v; edge[nCnt].c = c, edge[nCnt].next = pHead[u]; pHead[u] = nCnt;edge[++nCnt].v = u; edge[nCnt].c = 0, edge[nCnt].next = pHead[v]; pHead[v] = nCnt; } inline int SAP (int pStart, int pEnd, int N) {//層次點的數量 點的層次 點的允許弧 當前走過邊的棧int numh[INF], h[INF], curEdge[INF], pre[INF];//當前找到的流, 累計的流量, 當前點, 斷點, 中間變量int cur_flow, flow_ans = 0, u, neck, i, tmp;//清空層次數組,ms (h, 0); ms (numh, 0); ms (pre, -1);//將允許弧設為鄰接表的任意一條邊for (i = 0; i <= N; i++) curEdge[i] = pHead[i];numh[0] = N;//初始全部點的層次為0u = pStart;//從源點開始//如果從源點能找到增廣路while (h[pStart] <= N) {//找到增廣路if (u == pEnd) {cur_flow = 1e9;//找到當前增廣路中的最大流量, 更新斷點for (i = pStart; i != pEnd; i = edge[curEdge[i]].v)if (cur_flow > edge[curEdge[i]].c) neck = i, cur_flow = edge[curEdge[i]].c;//增加反向邊的容量for (i = pStart; i != pEnd; i = edge[curEdge[i]].v) {tmp = curEdge[i];edge[tmp].c -= cur_flow, edge[tmp ^ 1].c += cur_flow;}flow_ans += cur_flow;//累計流量u = neck;//從斷點開始找新的增廣路 }//找到一條允許弧for ( i = curEdge[u]; i != 0; i = edge[i].next)if (edge[i].c && h[u] == h[edge[i].v] + 1) break;//繼續DFSif (i != 0) {curEdge[u] = i, pre[edge[i].v] = u;u = edge[i].v;}//當前起點沒有允許弧,從u找不到增廣路else {//u所在的層次點減少一,且如果沒有與當前點一個層次的點, 退出.if (0 == --numh[h[u]]) continue;//有與u相同層次的點, 更新u的層次 ,回到上一個點curEdge[u] = pHead[u];for (tmp = N, i = pHead[u]; i != 0; i = edge[i].next)if (edge[i].c) tmp = min (tmp, h[edge[i].v]);h[u] = tmp + 1;++numh[h[u]];if (u != pStart) u = pre[u];}}return flow_ans; } inline void build() {char ch;scanf ("%d %d", &n, &m);ms (g, -1), ms (pHead, 0), nCnt = 1;for (int i = 1; i <= n; i++) {getchar();for (int j = 1; j <= m; j++) {ch = getchar();if (ch == '.') g[i][j] = 0;if (ch == 'D') g[i][j] = 1;}}n += 2, m += 2;SS = n * m, ST = SS + 1;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {int u = i * m + j;if (i == 0 || i == n - 1 || j == 0 || j == m - 1) {addEdge (u, ST, 4);continue;}if (g[i][j] == 0) {for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];int v = m * x + y;if (g[x][y] != 1) addEdge (u, v, 1);}}if (g[i][j] == 1) {addEdge (SS, u, 4);for (int k = 0; k < 4; k++) {int x = i + dx[k], y = j + dy[k];int v = m * x + y;if (g[x][y] != 1 ) addEdge (u, v, 1);}}}} } int cs; int main() {/*建圖,前向星存邊,表頭在pHead[],邊計數 nCnt.SS,ST分別為源點和匯點*/scanf ("%d", &cs);while (cs--) {build();printf ("%d\n", SAP (SS, ST, n * m + 1) );}return 0; } View Code?
轉載于:https://www.cnblogs.com/keam37/p/4293602.html
總結
以上是生活随笔為你收集整理的LA 6474 Drop Zone (最小割)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】不用软件,解压Win8/Win8.
- 下一篇: 【Go语言】【4】GO语言类型和为类型增