网络流建模关键1:有点的流量限。

 [SCOI2007]蜥蜴

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

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

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

【样例输入】
5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........

【样例输出】
1

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

这道题关键在于每个点有点的流量,遇到这种情况通常将一个拆成两个点,一条弧。

并且这种建模还有两个关键,就是自设源点和汇点。

代码如下用的直接定义法EK

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#define RC 20+2
#define inf 1e9
#define E 50000
#define N 4000+1 
using namespace std;
char g1[RC][RC],g2[RC][RC];
int map[RC][RC];
int used[E],way[E];
int head[N],arnum=1;
struct arc{
    int next,to,cap;
}ar[E];
void add(int from,int to,int cap)
{
    ar[++arnum].next=head[from];
    ar[arnum].to=to;
    ar[arnum].cap=cap;
    head[from]=arnum;
}
void insert(int from,int to,int cap){add(from,to,cap);add(to,from,0);}
int ans;
void work(int step)
{
    ans+=1;
    for(int i=1;i<=step;i++)ar[way[i]].cap--,ar[way[i]^1].cap++;
}
int dfs(int u,int en,int step)
{
    used[u]=1;
    for(int i=head[u];i;i=ar[i].next)
    {
        int v=ar[i].to;
        int cap=ar[i].cap;
        if(!used[v]&&cap>0)
        {
            way[step]=i;
            if(v==en){work(step);return 1;}
            else if(dfs(v,en,step+1))return 1;
        }
    }
    return 0;
}
int main()
{
    int r,c,d;scanf("%d%d%d",&r,&c,&d);
    int rank=0;
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
        {    
            cin>>g1[i][j];
            if(g1[i][j]!='0')
            {
                rank++;
                map[i][j]=rank;
                insert(rank,rank+450,g1[i][j]-48);
            }
        }        
    int st=0;
    int cnt=0;
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
        {
            cin>>g2[i][j];
            if(g2[i][j]=='L')
                insert(st,map[i][j],1),cnt++;
        }    
    int en=N-1;
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
        {
            if(g1[i][j]!='0')
            {
                for(int k=1;k<=r;k++)
                    for(int h=1;h<=c;h++)
                    {
                        double dx=abs(k-i);
                        double dy=abs(h-j);
                        if(hypot(dx,dy)&&sqrt(d*d)>=hypot(dx,dy)&&g1[k][h]!='0')
                            insert(map[i][j]+450,map[k][h],inf);
                    }
                if(r-i<d||i-1<d||c-j<d||j-1<d)
                    insert(map[i][j]+450,en,inf);            
            }
        }
    for(;;)
    {
        memset(used,0,sizeof(used));
        if(!dfs(st,en,1))break;
    }
    printf("%d",(cnt-ans)?(cnt-ans):0);
    return 0;
}

 

posted @ 2017-10-06 10:56  star_eternal  阅读(245)  评论(0编辑  收藏  举报