【bzoj1066】[SCOI2007]蜥蜴 网络最大流

【bzoj1066】[SCOI2007]蜥蜴

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

HINT

 

100%的数据满足:1<=r, c<=20, 1<=d<=3

 

代码

对于每根石柱,采取一分为二的想法,即把一个点分为两个点(可抽象为石柱底部到顶部),其连线容量限制为石柱高度。

超级源与所有有蜥蜴的点相连,容量为1。

超级汇与地图内所有能跳出的点的底端相连,容量为INF。

对于地图内任意两个石柱,如果间距小于d,就将其中一根石柱的底部与另一根石柱的顶部相连,其连线容量为INF。

构图完成,剩下就是跑一遍最大流,然后用蜥蜴数量减去最大流就是最终结果。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
//***************************
namespace NetFlow
{
const int MAXN=100000,MAXM=500000,inf=1e9;
struct Edge
{
    int v,c,f,nx;
    Edge() {}
    Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
void init(int _n)
{
    N=_n,sz=0;
    memset(G,-1,sizeof(G[0])*N);
}
void link(int u,int v,int c)
{
    E[sz]=Edge(v,c,0,G[u]);
    G[u]=sz++;
    E[sz]=Edge(u,0,0,G[v]);
    G[v]=sz++;
}
int ISAP(int S,int T)
{
    //S -> T
    int maxflow=0,aug=inf,flag=false,u,v;
    for (int i=0; i<N; ++i)cur[i]=G[i],gap[i]=dis[i]=0;
    for (gap[S]=N,u=pre[S]=S; dis[S]<N; flag=false)
    {
        for (int &it=cur[u]; ~it; it=E[it].nx)
        {
            if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+1)
            {
                if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
                pre[v]=u,u=v;
                flag=true;
                if (u==T)
                {
                    for (maxflow+=aug; u!=S;)
                    {
                        E[cur[u=pre[u]]].f+=aug;
                        E[cur[u]^1].f-=aug;
                    }
                    aug=inf;
                }
                break;
            }
        }
        if (flag) continue;
        int mx=N;
        for (int it=G[u]; ~it; it=E[it].nx)
        {
            if (E[it].c>E[it].f&&dis[E[it].v]<mx)
            {
                mx=dis[E[it].v];
                cur[u]=it;
            }
        }
        if ((--gap[dis[u]])==0) break;
        ++gap[dis[u]=mx+1];
        u=pre[u];
    }
    return maxflow;
}
bool bfs(int S,int T)
{
    static int Q[MAXN];
    memset(dis,-1,sizeof(dis[0])*N);
    dis[S]=0;
    Q[0]=S;
    for (int h=0,t=1,u,v,it; h<t; ++h)
    {
        for (u=Q[h],it=G[u]; ~it; it=E[it].nx)
        {
            if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
            {
                dis[v]=dis[u]+1;
                Q[t++]=v;
            }
        }
    }
    return dis[T]!=-1;
}
int dfs(int u,int T,int low)
{
    if (u==T) return low;
    int ret=0,tmp,v;
    for (int &it=cur[u]; ~it&&ret<low; it=E[it].nx)
    {
        if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
        {
            if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
            {
                ret+=tmp;
                E[it].f+=tmp;
                E[it^1].f-=tmp;
            }
        }
    }
    if (!ret) dis[u]=-1;
    return ret;
}
int dinic(int S,int T)
{
    int maxflow=0,tmp;
    while (bfs(S,T))
    {
        memcpy(cur,G,sizeof(G[0])*N);
        while (tmp=dfs(S,T,inf)) maxflow+=tmp;
    }
    return maxflow;
}
}
using namespace NetFlow;
double dist(int a,int b,int x,int y)
{
    return sqrt((b-y)*(b-y)+(a-x)*(a-x));
}
int  main()
{
    int n,m,d;
    char mp[33][33],mp2[33][33];
    cin>>n>>m>>d;
    init(1500);
    for(int i=1; i<=n; i++)
    {
        scanf("%s",mp[i]+1);
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%s",mp2[i]+1);
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if((mp[i][j]-'0')>0)
            {
                for(int h=i-d; h<=i+d; h++)
                {
                    for(int k=j-d; k<=j+d; k++)
                    {
                        if(h==i&&j==k)continue;
                        if(h<0||k<0||h>n+1||k>m+1)
                            continue;
                        double dd=d*1.0;
                        if(dist(i,j,h,k)>dd)continue;
                        if(h==0||k==0||h==n+1||k==m+1)
                            link((i-1)*m+j+400,1000,inf);
                        else  link((i-1)*m+j+400,(h-1)*m+k,inf);
                    }
                }
                link((i-1)*m+j,(i-1)*m+j+400,mp[i][j]-'0');
            }

        }
    }
    int sum=0;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(mp2[i][j]=='L')
            {
                sum++;
                link(999,(i-1)*m+j,1);
            }
        }
    }
    cout<<sum-dinic(999,1000)<<endl;
    return 0;
}

 

补:

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 1e3+500, M = 1e3+20, mod = 1e9+7, inf = 2e9;

char s[30];
int head[N],S,T,r,c,d,t=2,h[N],height[30][30],q[N],ans;
struct edge{int to,next,v;}e[N*N];
void adds(int u,int v,int w) {e[t].next=head[u];e[t].to=v;e[t].v=w;head[u]=t++;}
void add(int u,int v,int w) {adds(u,v,w);adds(v,u,0);}

bool bfs() {
    memset(h,-1,sizeof(h));
    int l = 0, r = 1,now;
    q[l] = S;
    h[S] = 0;
    while(l!=r) {
        now=q[l++];if(l == 900) l=0;
        for(int i=head[now];i;i=e[i].next) {
            if(e[i].v&&h[e[i].to]==-1) {
                h[e[i].to] = h[now] + 1;
                q[r++]=e[i].to;
                if(r == 900) r = 0;
            }
        }
    }
    if(h[T] == -1) return 0;
    return 1;
}
int dfs(int x,int f) {
    if(x == T) return f;
    int used=0,w;
    for(int i=head[x];i;i=e[i].next) {
        if(e[i].v&&h[e[i].to] == h[x]+1) {
            w = dfs(e[i].to,min(f-used,e[i].v));
            used+=w;e[i].v-=w;e[i^1].v+=w;
            if(used == f) return f;
        }
    }
    return used;
}
void dinic() {while(bfs()) ans+=dfs(S,inf);}

double dis(int i,int j,int k,int h) {return sqrt(1.0*(i-k)*(i-k) + 1.0*(j-h)*(j-h));}
int main() {
    scanf("%d%d%d",&r,&c,&d);
    S=3*r*c,T=S+1;
    for(int i = 1; i <= r; ++i)
    {
        scanf("%s",s+1);
        for(int j = 1; j <= c; ++j)
        {
            height[i][j] = s[j]-'0';
            add((i-1)*c+j,(i-1)*c+j+r*c,height[i][j]);
            if(i-d<=0||j-d<=0||i+d>r||j+d>c)
            {
                add((i-1)*c+j+r*c,T,inf);
            }
        }
    }
    int sum = 0;
    for(int i = 1; i <= r; ++i)
    {
        scanf("%s",s+1);
        for(int j = 1; j <= c; ++j) {
            if(s[j] == 'L')
            {
                sum++;
                add(S,(i-1)*c+j,1);
            }
            for(int k = 1; k <= r; ++k)
            for(int h = 1; h <= c; ++h) {
                if((k!=i||j!=h) && dis(i,j,k,h) <= 1.0*d)
                {
                    add((i-1)*c+j+r*c,(k-1)*c+h,inf);
                }
            }
        }
    }
    dinic();
    printf("%d\n",sum-ans);
    //cout<<sum-ans<<endl;
    return 0;
}
dinic

 

posted @ 2015-08-16 10:38  meekyan  阅读(194)  评论(0编辑  收藏  举报