码迷,mamicode.com
首页 > 其他好文 > 详细

[SCOI2007]蜥蜴

时间:2020-07-11 22:36:29      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:class   std   register   pop   front   怎么   main   div   while   

日常网络流.

题目大意:

  在一个n*m的矩阵中,每个格子有一定的高度,当高度为0时该格子便不存在,现在这个矩阵中有若干只蜥蜴,每只蜥蜴可以跳到距离不大于d的格子,问有几只蜥蜴无法逃离.

解题思路:

  一开始看到这道题迷了好久,知道是网络流但是不懂怎么建边,仔细分析了一波题解,发现思路其实很清晰.

  首先,由于格子有权值,于是想到拆点,一只蜥蜴想逃离,路线如下:源点-->柱顶1-->柱底1-->......-->柱顶p-->柱底p-->汇点,这样便可在保证柱子权值的情况下,求出可以逃离的蜥蜴最大数量.

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define R register
#define next mlgvegetable
#define debug puts("mlg")
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writesp(ll x);
inline void writeln(ll x);
ll n,m,k;
ll tot=1,head[100100],next[100100],c[100100],to[100100];
inline void add(ll x,ll y,ll z){
    to[++tot]=y;next[tot]=head[x];head[x]=tot;c[tot]=z;
    to[++tot]=x;next[tot]=head[y];head[y]=tot;c[tot]=0;
}
ll d[100010];
queue<ll>q;
ll S,T;
inline bool bfs(){
    while(q.size())q.pop();
    memset(d,0,sizeof d);
    d[S]=1;q.push(S);
    while(q.size()){
        ll x=q.front();q.pop();
        for(R ll i=head[x],ver;i;i=next[i]){
            ver=to[i];
            if(c[i]&&!d[ver]){
                d[ver]=d[x]+1;
                q.push(ver);
                if(ver==T) return true;
            }
        }
    }
    return false;
}
inline ll dinic(ll x,ll flow){
    if(x==T||!flow) return flow;
    ll k,rest=flow;
    for(R ll i=head[x],ver;i&&rest;i=next[i]){
        ver=to[i];
        if(d[ver]==d[x]+1&&c[i]){
            k=dinic(ver,min(rest,c[i]));
            if(!k) d[ver]=0;
            c[i]-=k;c[i^1]+=k;rest-=k;
        }
    }
    return flow-rest;
}
inline ll calc(ll x,ll y){
    return (x-1)*m+y+n*m;
}
inline bool check(ll x,ll y,ll u,ll v){
    return (x-u)*(x-u)+(y-v)*(y-v)<=k*k;
}
ll calc1(ll x,ll y){
    return (x-1)*m+y;
}
inline ll Read();
ll mpt[30][30];
int main(){
    n=read(),m=read(),k=read();
    S=n*m*2+1;T=S+1;
    for(R ll i=1;i<=n;i++){
        for(R ll j=1;j<=m;j++){
            if(mpt[i][j]=Read()){
                if(i-k<=0||i+k>n||j-k<=0||j+k>m){
                    add(calc(i,j),T,0x7fffffff);    
                }
            }
        }
    }
    for(R ll i=1;i<=n;i++){
        for(R ll j=1;j<=m;j++){
            if(mpt[i][j]){
                add(calc1(i,j),calc(i,j),mpt[i][j]);
                for(R ll u=1;u<=n;u++){
                    for(R ll v=1;v<=m;v++){
                        if((i==u&&j==v)||!mpt[u][v]) continue;
                        if(check(i,j,u,v)) add(calc(i,j),calc1(u,v),0x7fffffff);
                    }
                }
            }
        }
    }
    ll ans=0;
    for(R ll i=1;i<=n;i++){
        for(R ll j=1;j<=m;j++){
            char c=getchar();while(c!=.&&c!=L) c=getchar();
            if(c==L){
                add(S,calc1(i,j),1);
                ans++;
            }
        }
    }
    ll _flow;
    while(bfs()){while(_flow=dinic(S,0x7fffffff)) ans-=_flow;}
    writeln(ans);
}
inline ll Read(){
    char ch=getchar();
    while(ch<0||ch>9) ch=getchar();
    return ch-0;
}
inline ll read(){
    ll x=0,t=1;char ch=getchar();
    while(ch<0||ch>9){
        if(ch==-) t=-1;
        ch=getchar();
    }
    while(ch>=0&&ch<=9){
        x=x*10+ch-0;
        ch=getchar();
    }
    return x*t;
}
inline void write(ll x){
    if(x<0){putchar(-);x=-x;}
    if(x<=9){putchar(x+0);return;}
    write(x/10);putchar(x%10+0);
}
inline void writesp(ll x){
    write(x);putchar( );
}
inline void writeln(ll x){
    write(x);putchar(\n);
}

(代码十分拙劣,懒得改了...)

[SCOI2007]蜥蜴

标签:class   std   register   pop   front   怎么   main   div   while   

原文地址:https://www.cnblogs.com/ylwtsq/p/13285693.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!