您的位置:首页 > 其它

【bzoj1066】[SCOI2007]蜥蜴

2017-06-19 12:33 423 查看

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3997  Solved: 2018

[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

HINT

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

Source

Pku 2711 Leapin' Lizards

[Submit][Status][Discuss]


一眼网络流。

然后发现蒟蒻并不会处理点权的问题

然后看学长的题解

然后觉得自己好菜。。。

点权的问题就是把一个点拆成一个入点和一个出点

然后入点和出点连一条边,容量为点权

即所谓拆点法

具体到这一题中

就是把每个石柱拆成两个点,一个入点一个出点,容量为石柱的高度

如果说从石柱a能跳到石柱b,那么就从a到b连一条边,容量为INF

如果说从石柱a能跳到边界外,那么就从a到汇点T连一条边,容量为INF

如果说从石柱a上有蜥蜴,那么就从源点S向a连一条边,容量为INF

然后跑最大流

答案即为蜥蜴总数-最大流

蒟蒻居然一直在纠结双向建边会不会影响最大流的问题(事实上是不用考虑的)。。。。真是菜啊

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 500;
const int maxc = 25;
const int maxr = 25;
const int INF = 2147483647;

struct data{
int from,to,cap,flow;
}e[10 * maxn * maxn];

queue<int> Q;
vector<int> G[2 * maxn];
int a[maxc][maxr],id[maxc][maxr],in[maxn],out[maxn];
int tot_e = -1,tot_p,tot_id,n,m,d,ans,s,t;
bool vis[2 * maxn];
int dis[2 * maxn],cur[2 * maxn];

inline int getint()
{
int ret = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
ret = ret * 10 + c - '0',c = getchar();
return ret;
}

inline bool getcom()
{
char c = getchar();
while (c != '.' && c != 'L') c = getchar();
if (c == 'L') return 1;
else return 0;
}

inline int getsingle()
{
char c = getchar();
while (c < '0' || c > '9') c = getchar();
return c - '0';
}

inline void add(int u,int v,int w)
{
e[++tot_e] = (data){u,v,w,0};
G[u].push_back(tot_e);
e[++tot_e] = (data){v,u,w,w};
G[v].push_back(tot_e);
}

inline bool bfs()
{
memset(vis,0,sizeof(vis));
Q.push(s);
vis[s] = 1;
while (!Q.empty())
{
int u = Q.front();
Q.pop();
for (int i = 0; i < G[u].size(); i++)
{
data edge = e[G[u][i]];
int v = e[G[u][i]].to;
if (!vis[v] && edge.flow < edge.cap)
{
dis[v] = dis[u] + 1;
vis[v] = 1;
Q.push(v);
}
}
}
return vis[t];
}

inline int dinic(int o,int b)
{
if (o == t || b == 0) return b;
int flow = 0;
for (int& i = cur[o]; i < G[o].size(); i++)
{
data& edge = e[G[o][i]];
int v = edge.to;
if (dis[v] != dis[o] + 1) continue;
int f = dinic(v,min(b,edge.cap - edge.flow));
if (f)
{
edge.flow += f;
e[G[o][i] ^ 1].flow -= f;
flow += f;
b -= f;
if (b == 0) break;
}
}
return flow;
}

int main()
{
n = getint(); m = getint(); d = getint();
s = 0; t = 1; tot_p = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = getsingle();

for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (a[i][j])
{
id[i][j] = ++tot_id;
in[tot_id] = ++tot_p;
out[tot_id] = ++tot_p;
add(in[tot_id],out[tot_id],a[i][j]);
}

for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
if (!a[i][j]) continue;
if (i <= d || n + 1 - i <= d || j <= d || m + 1 - j <= d) add(out[id[i][j]],t,INF);
for (int k = 1; k <= n; k++)
for (int l = 1; l <= m; l++)
{
if (i == k && j == l) continue;
if (abs(i - k) + abs(j - l) <= d && a[k][l])
add(out[id[i][j]],in[id[k][l]],INF);
}
}

for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (getcom())
{
add(s,in[id[i][j]],1);
ans++;
}
while (bfs())
{
memset(cur,0,sizeof(cur));
ans -= dinic(s,INF);
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: