hdu2732 Leapin' Lizards

题目的大意是有个n*m的grid,每个位置上都有柱子,柱子有一定的高度,有一群lizard想逃出这个grid,lizard一次最远可以跳d。

grid的四边是安全的,每个柱子一次上面最多有一只lizard,lizard可以跳到一个可以跳到且上面没有lizard的柱子上面同时它原来所在的柱子的高度会-1,为0时就不能再往上面跳了。

思路就是把柱子拆点,容量为其高度。lizard可以一次性从其跳到安全区的话就和汇点t连接,容量为inf;上面有人的话就和源点s连接,容量为1。

两个柱子的距离在d之内也连接起来,容量为inf。

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2016
File Name   :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1100;
const int maxm = 1400000;
char mp1[maxn][maxn],mp2[maxn][maxn];
int n, d, m;
int s, t;
int head[maxn], cap[maxm], flow[maxm], nxt[maxm],pnt[maxm];
int ecnt;
inline void Addedge(int u,int v,int c) {
    pnt[ecnt] = v, flow[ecnt] = 0, cap[ecnt] = c;
    nxt[ecnt] = head[u], head[u] = ecnt++;

    pnt[ecnt] = u, flow[ecnt] = 0, cap[ecnt] = 0;
    nxt[ecnt] = head[v], head[v] = ecnt++;
}
inline void Input() {
    scanf("%d%d",&n,&d);

    for (int i = 1;i <= n;++i)
        scanf("%s",mp1[i] + 1);

    for (int i = 1;i <= n;++i)
        scanf("%s",mp2[i] + 1);

    m = strlen(mp1[1] + 1);
    s = n*m*2+1,t = s + 1;

    memset(head, -1,sizeof head);
    ecnt = 0;
}
inline int Getmap() {
    //拆点
    for (int i = 1;i <= n;++i) {
        for (int j = 1;j <= m;++j) {
            if (mp1[i][j] - '0') {//柱子上面可以跳
                Addedge((i-1)*m+j, n*m+(i-1)*m+j, mp1[i][j] - '0');
            }
        }
    }

    int cnt = 0;
    for (int i = 1;i <= n;++i) {
        for (int j = 1;j <= m;++j) {
            if (mp2[i][j] == 'L') {//这个位置上有人
                Addedge(s, (i-1)*m+j, 1);cnt++;
            }
        }
    }

    for (int i = 1;i <= n;++i) {
        for (int j = 1;j <= m;++j) {
            if (i <= d || j <= d || j > m - d || i > n - d)
                Addedge((i-1)*m+j + n*m, t, INF);
        }
    }

    for (int i = 1;i <= n;++i) {
        for (int j = 1;j <= m;++j) {
            for (int l = 1;l <= n;++l) {
                for (int r = 1;r <= m;++r) {
                    if (!(i==l && j==r) && abs(i-l) + abs(j-r) <= d)
                        Addedge((i-1)*m+j+n*m,(l-1)*m+r, INF); 
                }
            }
        }
    }
    return cnt;
}

int dis[maxn];
bool vis[maxn];

bool spfa() {
    queue<int> que;
    memset(dis, -1,sizeof dis);
    memset(vis, false,sizeof vis);
    que.push(s);
    dis[s] = 0;
    vis[s] = true;
    while(!que.empty()) {
        int u = que.front();
        que.pop();
        for (int i = head[u];i != -1;i = nxt[i]) {
            int v = pnt[i];
            if (cap[i] - flow[i] > 0 && dis[v] == -1) {
                dis[v] = dis[u] + 1;
                que.push(v);
            }
        }
    }
    return dis[t] != -1;
}

int dfs(int u,int a) {
    if (u == t || a == 0) return a;
    int ret = 0,f;
    for (int i = head[u];i != -1;i = nxt[i]) {
        int v = pnt[i];
        if (dis[v] > dis[u] && (f = dfs(v, min(a, cap[i] - flow[i]))) > 0) {
            ret += f;
            a -= f;
            flow[i] += f;
            flow[i^1] -= f;
            if (a==0)break;
        }
    }
    return ret;
}

inline int dinic() {
    int ret = 0;
    while(spfa()) {
        ret += dfs(s, INF);
    }
    return ret;
}
int main()
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    int tt;
    scanf("%d",&tt);
    int icase = 0;
    while(tt--) {
        Input();
        int cnt = Getmap();
        int ans = dinic();
        // printf("cnt = %d, ans = %d\n",cnt,ans);
        printf("Case #%d: ", ++icase);
        if (cnt == ans) printf("no lizard was left behind.\n");
        if (ans + 1 == cnt) printf("1 lizard was left behind.\n");
        if (ans + 1 < cnt) printf("%d lizards were left behind.\n", cnt - ans);
    }
    return 0;
}


你可能感兴趣的:(最大流,拆点)