1. 程式人生 > >bzoj1001狼抓兔子——網路流平面圖問題

bzoj1001狼抓兔子——網路流平面圖問題

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 25715  Solved: 6529
[Submit][Status][Discuss]

Description

現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形:

 

左上角點為(1,1),右下角點為(N,M)(上圖中N=4,M=5).有以下三種類型的道路  1:(x,y)<==>(x+1,y)  2:(x,y)<==>(x,y+1)  3:(x,y)<==>(x+1,y+1)  道路上的權值表示這條路上最多能夠通過的兔子數,道路是無向的. 左上角和右下角為兔子的兩個窩, 開始時所有的兔子都聚集在左上角(1,1)的窩裡,現在它們要跑到右下解(N,M)的窩中去,狼王開始伏擊 這些兔子.當然為了保險起見,如果一條道路上最多通過的兔子數為K,狼王需要安排同樣數量的K只狼, 才能完全封鎖這條道路,你需要幫助狼王安排一個伏擊方案,使得在將兔子一網打盡的前提下,參與的 狼的數量要最小。因為狼還要去找喜羊羊麻煩.

Input

第一行為N,M.表示網格的大小,N,M均小於等於1000. 接下來分三部分 第一部分共N行,每行M-1個數,表示橫向道路的權值.  第二部分共N-1行,每行M個數,表示縱向道路的權值.  第三部分共N-1行,每行M-1個數,表示斜向道路的權值.  輸入檔案保證不超過10M

Output

輸出一個整數,表示參與伏擊的狼的最小數量.

Sample Input

3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6

Sample Output

14

HINT

 2015.4.16新加資料一組,可能會卡掉從前可以過的程式。

Source


HOME
Back

其實就是一道模板題……然而建成了單向邊……用的是isap,雙向邊只需要在建邊的時候把反向邊建成cap就好了

inline void add_edge(int x, int y, int cap) {
    e[p] = Edge(y, h[x], cap, 0); h[x] = p++;
    e[p] = Edge(x, h[y], cap, 0); h[y] = p++;
}

然後……沒有然後

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000003;
const int MAXE = 6000003;
const int INF = 0x3f3f3f3f;
struct Edge{
    int to, nxt, cap, flow;
    Edge() {}
    Edge(int to, int nxt, int cap, int flow):to(to), nxt(nxt), cap(cap), flow(flow) {}
}e[MAXE];
int n, m;
int h[MAXN], p;
int source, sink, tot;
int pre[MAXN], num[MAXN], cur[MAXN];
int d[MAXN];
bool vis[MAXN];
queue<int> q;
 
inline void add_edge(int x, int y, int cap) {
    e[p] = Edge(y, h[x], cap, 0); h[x] = p++;
    e[p] = Edge(x, h[y], cap, 0); h[y] = p++;
}
 
void bfs() {
    memset(vis, 0, sizeof(vis));
    q.push(sink);
    vis[sink] = 1;
    d[sink] = 0;
    while(!q.empty()) {
        int u = q.front(); q.pop();
        num[d[u]]++;
        for(int i = h[u]; ~i; i = e[i].nxt) {
            int v = e[i].to;
            if(!vis[v]) {
                vis[v] = 1;
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
}
 
void augment(int flow) {
    for(int i = source; i != sink; i = e[cur[i]].to) {
        e[cur[i]].flow += flow;
        e[cur[i] ^ 1].flow -= flow;
    }
}
 
int isap() {
    memset(num, 0, sizeof(num));
    bfs();
    memcpy(cur, h, sizeof(h));
    int u = source, flow = 0, f = INF;
    while(d[source] < tot) {
        bool fg = 0;
        for(int i = cur[u]; ~i; i = e[i].nxt) {
            if(e[i].cap > e[i].flow && d[u] == d[e[i].to] + 1) {
                pre[e[i].to] = u;
                cur[u] = i;
                u = e[i].to;
                f = min(f, e[i].cap - e[i].flow);
                fg = 1;
                if(u == sink) {
                    flow += f;
                    augment(f);
                    f = INF;
                    u = source;
                }
                break;
            }
        }
        if(fg) continue;
        if(--num[d[u]] == 0) break;
        int M = tot - 1;
        for(int i = h[u]; ~i; i = e[i].nxt) {
            if(e[i].cap > e[i].flow && M > d[e[i].to]) {
                M = d[e[i].to];
                cur[u] = i;
            }
        }
        num[d[u] = M + 1]++;
        if(u != source) u = pre[u];
    }
    return flow;
}
signed main() {
    scanf("%d%d",&n,&m);
    int x;
    source = 1; sink = n * m; tot = sink;
    memset(h, -1, sizeof(h));
    for(int i = 1; i <= n; i++)
        for(int j = 1; j < m; j++)
        {
            scanf("%d",&x);
            add_edge(m * (i - 1) + j, m * (i - 1) + j + 1, x);
        }
    for(int i = 1; i < n; i++)
        for(int j = 1; j <= m; j++)
        {
            scanf("%d",&x);
            add_edge(m * (i - 1) + j, m * (i) + j, x);
        }
    for(int i = 1; i < n; i++)
        for(int j = 1; j < m; j++)
        {
            scanf("%d",&x);
            add_edge(m * (i - 1) + j, m * (i) + j + 1, x);
        }
    printf("%d\n", isap());
} 



相關推薦

bzoj1001兔子——網路平面圖問題

1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 25715  Solved: 6529 [Submit][Status][Discuss] Description 現在小朋

bzoj1001 兔子 網路(水)

這道題正解不是網路流,但是網路流(最小割)在這種圖上跑得飛起,就能水(2016.8.12)。直接貼程式碼。 #include<iostream> #include<cstdio> #include<queue> usin

BZOJ1001兔子(網路最小割)

BZOJ1001 狼抓兔子 題目描述 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M

[日常摸魚]bzoj1001兔子-最大最小割

百萬 reg ret 最短 fin 網絡圖 通過 聯通 gpo 題意就是求最小割… 然後我們有這麽一個定理(最大流-最小割定理 ): 任何一個網絡圖的最小割中邊的容量之和等於圖的最大流。 (下面直接簡稱為最大流和最小割) 證明: 如果最大流>最小割,那把這些割邊刪去之

BZOJ1001:兔子(最小割最大+vector模板)

cout 地形 ++ 能夠 can 圖片 jpg http img 1001: [BeiJing2006]狼抓兔子 Description 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的,而且現在的兔子還比較笨,它們只有兩個窩,現在

BZOJ1001兔子(平面圖最小割)

題目大意:給一個n*m的網格圖,表示一個地圖。起點(1,1),終點(n,m)。每條邊上有一個權值,表示該路徑上的兔流量。現在一些兔子從起點沿著邊跑到終點。然後有一些大灰狼要抓這些兔子。一隻狼能抓一隻兔子。現在狼王想知道至少要派多少狼能堵住兔子的路。 題目分析:很裸的最小割

bzoj1001兔子

n) std 灰太狼 top bool 表示 continue 能夠 long 1001: [BeiJing2006]狼抓兔子 現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對

【dinic模板】BZOJ1001 兔子

#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace st

BZOJ1001 兔子

最小割 程式碼 # include <bits/stdc++.h> # define IL inline # define RG register # define Fill(a, b) memset(a, b, sizeof(a)) # def

兔子 HYSBZ - 1001(網路/平面圖轉對偶圖求最短路)

傳送門 題意:有個方格,求從(1,1)到(n,m)的最小割 題解:有兩種方法,第一種:使用dinic演算法,但是需要有個優化就是當每次增廣時,如果一旦哪條路增廣失敗,那麼就把這條路直接賦值為-1,把它堵死,這樣優化可以達到很高。 附上第一種程式碼:(使用白書上的dinic演算法呢,可以過

BZOJ1001[BeiJing2006]兔子最小割網路

Description 現在小朋友們最喜歡的”喜羊羊與灰太狼”,話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M)(上圖中N=

BZOJ1001 [BeiJing2006]兔子網路最小割)

題目可以轉化為:從原圖中選出一個邊集,使得去掉它之後,(1,1)與(n,m)不通  即:以(1,1)為源,(n,m)為匯,求該圖最小割  不過由於節點過多,直接對輸入的圖求最小割的話會超時  轉化:求

bzoj1001 [BeiJing2006]兔子網路dinic演算法||最短路spfa)

1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MB Submit: 24017  Solved: 6

[BZOJ1001][BeiJing2006]兔子 && 平面網路

傳說這個題可以轉最短路 於是我去轉最短路 於是搞的我無比糾結 連邊麻煩的要死 #include<cstdio> #include<algorithm> #include<cstring> #include<iostream>

平面圖轉對偶圖(Bzoj1001兔子)

fin con names esp || ons down ace ++ 如果只會用最小割做這道題那就太菜辣 引入 來自某學長 平面圖:在平面上邊不相交的圖(邊可以繞著畫) 那麽平面圖的邊與邊就圍成了許多個區域(這與你畫圖的方式有關) 定義對偶圖:把相鄰的兩個區域連上邊,形

BZOJ1001 [BeiJing2006]兔子 平面圖轉對偶圖,最小割轉最短路

bits ges code inf 如果 對偶圖 += ron oid 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 28885 Solved: 7540[Submit

1001: [BeiJing2006]兔子[dinic網路]

現在小朋友們最喜歡的"喜羊羊與灰太狼",話說灰太狼抓羊不到,但抓兔子還是比較在行的, 而且現在的兔子還比較笨,它們只有兩個窩,現在你做為狼王,面對下面這樣一個網格的地形: 左上角點為(1,1),右下角點為(N,M)(上圖中N=4,M=5).有以下三種類型的道路 1:(x,y)<

[BJOI2006]兔子——最小割轉對偶圖最短路 [無效]網路之轉換對偶圖

其實這個題直接Dinic跑最小割可過。 (小優化是: 無向圖建網路流,一條邊不用建成4條,可以正反容量都是邊權即可。完全等價 )   [無效]網路流之轉換對偶圖   一個巧妙的事情是,如果建邊合適的話,最小割就是右上部分到左下部分的最短路。 看圖就明白了。 注意一個正方形

BZOJ1001】【Beijing2006】兔子平面圖轉對偶圖:最小割+最短路)

題目描述 傳送門 題解 題目描述很明顯這就是一道最小割,不過跑最大流的話會TLE。 我們發現這是一個平面圖(什麼是平面圖?),那麼我們就可以參考平面圖轉對偶圖的思想,將這道題轉化成最短路。

bzoj1001: [BeiJing2006]兔子(最大

題目傳送門 解法: 每一隻兔子就需要一隻狼。 那麼我們只需要求出最多能通過多少隻兔子即可。 然後就派多少隻狼就行了唄。。 因為兔子從哪裡過來的我就在哪裡放狼。 所以狼的數量一定等於最多兔子通過的數量 題目並不要求求方案,所以不需知道兔子從哪過來。