您的位置:首页 > 其它

【codevs2440】【BZOJ1066】蜥蜴,最大流

2016-05-29 08:05 309 查看
Time:2016.05.29

Author:xiaoyimi

转载注明出处谢谢

思路:

(水题硬是让我调了1h+)

a[i][j]为第i行第j列的石柱高度

把每个石柱i拆成两个点pi,qi,连边流量为a[i][j],如果上面有蜥蜴就连一条s到pi的点,流量为1,如果i能跳出边界,就连一条qi到t的边,流量inf,然后qi向所有能到达的石柱pj连边(不能向自己连边),流量为inf。跑出来的最大流就是能跑出去的蜥蜴的最大数量

注意:

(为了图省事边读入边连边,结果调了好久)

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define inf 100000
using namespace std;
int n,m,d,tot=1,s,t;
int a[22][22],dis[1000],first[1000];
bool b[22][22];
struct edge{int v,w,next;}e[500010];
queue<int>q;
void add(int x,int y,int z)
{
e[++tot]=(edge){y,z,first[x]};first[x]=tot;
e[++tot]=(edge){x,0,first[y]};first[y]=tot;
}
bool bfs()
{
memset(dis,0,sizeof(dis));
q.push(s);dis[s]=1;
while (!q.empty())
{
int k=q.front();q.pop();
for (int i=first[k];i;i=e[i].next)
if (e[i].w&&!dis[e[i].v])
dis[e[i].v]=dis[k]+1,
q.push(e[i].v);
}
return dis[t];
}
int dfs(int x,int maxn)
{
if (x==t) return maxn;
int used=0;
for (int i=first[x];i;i=e[i].next)
if (dis[e[i].v]==dis[x]+1)
{
int k=dfs(e[i].v,min(maxn-used,e[i].w));
used+=k;
e[i].w-=k;e[i^1].w+=k;
if (used==maxn) return maxn;
}
if (!used) dis[x]=0;
return used;
}
bool cal(int x1,int y1,int x2,int y2){return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<=d*d;}
main()
{
scanf("%d%d%d",&n,&m,&d);
t=n*m*2+1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
char ch=getchar();
while (ch>'3'||ch<'0') ch=getchar();
a[i][j]=ch-'0';
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (a[i][j])
{
add((i-1)*m+j,(i-1)*m+j+n*m,a[i][j]);
if (d>=min(min(i,j),min(n-i+1,m-j+1)))
add((i-1)*m+j+n*m,t,a[i][j]);
for (int p=1;p<=n;p++)
for (int q=1;q<=m;q++)
if (a[p][q]&&(p!=i||q!=j)&&cal(i,j,p,q))
add((i-1)*m+j+n*m,(p-1)*m+q,a[i][j]);
}
int ans=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
char ch=getchar();
while (ch!='.'&&ch!='L') ch=getchar();
b[i][j]=(ch=='L');
if (b[i][j]) ans++,add(s,(i-1)*m+j,1);
}
while (bfs())
ans-=dfs(s,inf);
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: