1066: [SCOI2007]蜥蜴

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec   Memory Limit: 162 MB
Submit: 2614   Solved: 1284
[ Submit][ Status][ Discuss]

Description

在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

Input

输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

Output

输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

Sample Input

5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........

Sample Output

1



第一道网络流就搞了一周。。
反向弧容量是0!
反向弧容量是0!
反向弧容量是0!
写的时候一直以为反向弧容量是正向弧的相反数。。。
233


将每根石柱拆成两个点(入点和出点),连一条容量等于改石柱高度的边
然后一个超级源连接有蜥蜴的点
再用每个石柱的出点去连它能够得到的点的入点
如果能跳出去就和汇点连边
最后一发最大流。。。
bzoj上dicnic28ms,朴素算法40ms


#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<vector>
#include<map>
using namespace std;
  
const int maxn = 25;
const int INF = 1E9;
  
struct E{
    int flow,cap,from,to;
    E(){}
    E(int flow,int cap,int from,int to) : flow(flow),cap(cap),from(from),to(to) {}
}edgs[maxn*maxn*maxn*maxn*4];
  
int d,n,m,tot = 0,h[maxn][maxn],cur = 0,L[maxn*maxn*2+10],cnt[maxn*maxn*2+10];
int fa[maxn*maxn*2+10],a[maxn*maxn*2+10];
char p[maxn];
bool vis[maxn*maxn*2+10];
  
vector <int> G[maxn*maxn*2+10];
queue <int> q;
  
int num(int x,int y) {return m*(x-1)+y;}
  
void Add(int Num,int cap,int from,int to) {
    G[from].push_back(Num);
    edgs[Num] = E(0,cap,from,to);
}
  
int dis(int A,int B,int C,int D)
{
    int X = (A-C)*(A-C);
    int Y = (B-D)*(B-D);
    return X+Y;
}
  
bool BFS()
{
    memset(vis,0,sizeof(vis));
    memset(L,0,sizeof(L));
    vis[0] = 1; L[0] = 1;
    q.push(0);
    while (!q.empty()) {
        int k = q.front(); q.pop();
        for (int l = 0; l < G[k].size(); l++) {
            E e = edgs[G[k][l]];
            if (vis[e.to] || e.cap - e.flow <= 0) continue;
            vis[e.to] = 1;
            L[e.to] = L[k] + 1; q.push(e.to);
        }
    }
    return vis[n*m*2+1];
}
  
int DFS(int k,int a)
{
    if (a <= 0 || k == n*m*2+1) return a;
    int f,flow = 0;
    for (int &i = cnt[k]; i < G[k].size(); i++) {
        E &e = edgs[G[k][i]];
        if (L[e.to] == L[k]+1 && (f = DFS(e.to,min(e.cap - e.flow,a))) > 0) {
            flow += f;
            e.flow += f;
            a -= f;
            edgs[G[k][i]^1].flow -= f;
            if (a == 0) break;
        }
    }
    return flow;
}
  
void solve() {
    int x = n*m*2+1;
    while (x != 0) {
        edgs[fa[x]].flow += a[n*m*2+1];
        edgs[fa[x]^1].flow -= a[n*m*2+1];
        x = edgs[fa[x]].from;
    }
}
  
int main()
{
    #ifdef YZY  
        freopen("yzy.txt","r",stdin);
    #endif
      
    cin >> n >> m >> d;
    for (int i = 1; i <= n; i++) {
        scanf("%s",1+p);
        for (int j = 1; j <= m; j++)
            h[i][j] = p[j] - '0';
    }
    for (int i = 1; i <= n; i++) {
        scanf("%s",1+p);
        for (int j = 1; j <= m; j++)
            if (p[j] == 'L') {
                ++tot;
                Add(cur++,1,0,num(i,j));
                Add(cur++,0,num(i,j),0);
            }
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (h[i][j]) {
                int N = num(i,j);
                Add(cur++,h[i][j],N,N+n*m);
                Add(cur++,0,N+n*m,N);
                if (i + d > n || i - d < 1 || j + d > m || j - d < 1) {
                    Add(cur++,INF,N+n*m,n*m*2+1);
                    Add(cur++,0,n*m*2+1,N+n*m);
                }
                for (int i1 = 1; i1 <= n; i1++)
                    for (int j1 = 1; j1 <= m; j1++)
                        if ((i != i1 || j != j1) && dis(i,j,i1,j1) <= d*d) {
                            if (h[i1][j1]) {
                                int T = num(i1,j1);
                                Add(cur++,INF,N+n*m,T);
                                Add(cur++,0,T,N+n*m);
                            }
                        }
            }
      
    int flow = 0;
    while (BFS()) {
        memset(cnt,0,sizeof(cnt));
        flow += DFS(0,INF);
    }
    /* 
    for (;;) {
        memset(vis,0,sizeof(vis));
        vis[0] = 1; q.push(0);
        bool flag = 0; 
        a[0] = INF;
        while (!q.empty()) {
            int k = q.front(); q.pop();
            for (int l = 0; l < G[k].size(); l++) {
                E e = edgs[G[k][l]];
                if (vis[e.to] || e.cap - e.flow <= 0) continue;
                vis[e.to] = 1;
                fa[e.to] = G[k][l];
                a[e.to] = min(a[k],e.cap - e.flow);
                q.push(e.to);
            }
            if (vis[n*m*2+1]) {
                flow += a[n*m*2+1]; 
                solve();
                flag = 1; 
                while (!q.empty()) q.pop();
                break;
            }
        }
        if (!flag) break;
    }
    */
    cout << tot - flow;
    return 0;
}




反向弧容量是0!
反向弧容量是0!

你可能感兴趣的:(1066: [SCOI2007]蜥蜴)