hdu 2732 最大流

來源:互聯網
上載者:User

/*
    最大流  拆點   簡單圖論  SAP

    題意:有一些蜥蜴在一個迷宮裡面,求這些蜥蜴還有多少是無論如何都逃不出來的。蜥蜴最遠能夠跳躍距離D,若某一時刻蜥蜴能跳到迷宮外圍,則算>蜥蜴逃出來了。每隻蜥蜴有一個初始的位置,題目保證這些位置都有一些柱子,每次蜥蜴從一個位置跳到另外一個位置的時候,就會由於反作用力使得一根
柱子倒下。每根柱子都有最大jump數,若有超過jump個蜥蜴從該跟柱子跳過(也就是leap次),則柱子會倒塌。距離是算曼哈頓距離。

    建圖:初始有蜥蜴的柱子和source連邊,容量為1
          每個柱子拆成兩個點,u -> u',容量為jump數
          能跳到外圍的柱子和sink連邊,容量infinite
          相距不超過D的柱子u,v,連邊u' -> v 和 v' -> u,容量infinite

          有sap模板就是爽...建完圖就算完工了~~

*/


#include <stdio.h>#include <algorithm>#include <string>#include <iostream>#include <string.h>using namespace std;#define     debug   printf("!\n")#define     MAXN    550+550+100#define     MAXM    505000#define     INF     999999999#define     ABS(x)  ((x) > 0 ? (x) : (-(x)))int cur[MAXN], head[MAXN], aug[MAXN], pre[MAXN], gap[MAXN], dis[MAXN];struct Edge {    int u, v, next, cap;    Edge () { }    Edge (int u, int v, int next, int cap) : u(u), v(v), next(next), cap(cap) { }} edge[MAXM];int edge_num;void init(){    edge_num = 0;    memset(head, -1, sizeof(head));}void add_edge(int u, int v, int cap){    edge[edge_num] = Edge(u, v, head[u], cap);    head[u] = edge_num++;    edge[edge_num] = Edge(v, u, head[v], 0);    head[v] = edge_num++;}int SAP(int s, int sink, int n){    aug[s] = INF;    pre[s] = -1;    memset(dis, 0, sizeof(dis));    memset(gap, 0, sizeof(gap));    gap[0] = n;memcpy(cur, head, sizeof(head));    int max_flow = 0, u = s;    while(dis[s] < n) {        bool flag = false;        if(u == sink) {            max_flow += aug[sink];            for(int v = pre[sink]; v != -1; v = pre[v]) {       // 路徑回溯更新殘留網路                  int k = cur[v];                edge[k].cap -= aug[sink];                edge[k ^ 1].cap += aug[sink];                aug[v] -= aug[sink];                // 修改可增廣量,以後會用到                  if(edge[k].cap == 0) u = v;         // 不回退到源點,僅回退到容量為0的弧的弧尾              }        }        for(int k = cur[u]; k != -1; k = edge[k].next) {    // 從當前弧開始尋找允許弧              int v = edge[k].v;            if(edge[k].cap > 0 && dis[u] == dis[v] + 1) {   // 找到允許弧                  flag = true;                pre[v] = u;                cur[u] = k;                aug[v] = min(aug[u], edge[k].cap);                u = v;                break;            }        }        if(!flag) {            if(--gap[dis[u]] == 0) break;       /* gap最佳化,層次樹出現斷層則結束演算法 */            int mindis = n;            cur[u] = head[u];            for(int k = head[u]; k != -1; k = edge[k].next) {                int v = edge[k].v;                if(edge[k].cap > 0 && dis[v] < mindis) {                    mindis = dis[v];                    cur[u] = k;                 // 修改標號的同時修改當前弧                  }            }            dis[u] = mindis + 1;            gap[dis[u]]++;            if(u != s) u = pre[u];      // 回溯繼續尋找允許弧          }    }    return max_flow;}string map[25], lizards[25];int main(){    int cases, Cas = 0, row, D;    scanf("%d", &cases);    while(cases--) {        scanf("%d%d", &row, &D);        init();        for(int i = 0; i < row; i++) cin >> map[i];        int n = row, m = map[0].length();        int source = n*m*2, sink = source + 1;        for(int i = 0; i < n; i++)             for(int j = 0; j < m; j++) if(map[i][j] != '0')                add_edge(i*m+j, i*m+j + n*m, map[i][j] - '0');      //拆點        for(int i = 0; i < row; i++) cin >> lizards[i];        int sum = 0;        for(int i = 0; i < n; i++)            for(int j = 0; j < m; j++) if(lizards[i][j] == 'L') {                add_edge(source, i*m+j, 1);     //有蜥蜴的柱子                sum++;            }        for(int i = 0; i < n; i++)            for(int j = 0; j < m; j++) if(i < D || j < D || i > n - D - 1 || j > m - D - 1) {                add_edge(i*m+j + m*n, sink, INF);            }        for(int i = 0; i < n; i++)            for(int j = 0; j < m; j++)                for(int x = 0; x < n; x++)                    for(int y = 0; y < m; y++) if(!(x == i && y == j) && D >= ABS(x-i) + ABS(y-j)) {                        add_edge(i*m+j + n*m, x*m+y, INF);                    }        int result = SAP(source, sink, n*m*2+2);        printf("Case #%d: ", ++Cas);        if(sum == result) printf("no lizard was left behind.\n");        else if(sum == result + 1) printf("1 lizard was left behind.\n");        else printf("%d lizards were left behind.\n", sum - result);    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.