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

Luogu2472 SCOI2007蜥蜴

时间:2020-06-09 09:30:30      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:etc   long   http   ref   最大   har   spm   ret   拆点   

Description

link

Solution

首先几个地方指向网络流的常见套路

1.每个点有固定的经过次数:拆点,入点和出点之间连权值为次数的边

然后把能相互跳的点之间连 \(inf\) 的边,\(S\) 往蜥蜴连 \(1\) 的边,能跳出去的点往 \(T\)\(inf\) 的边

上面直接含义就能理解……

然后最大流

记得题目中的所求,所以应该是要用蜥蜴的数量减去 \(maxflow\)

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k==‘-‘) f=-1;
		while(isdigit(k)) res=res*10+k-‘0‘,k=getchar();
		return res*f;
	}
	const int M=2e5+10,N=2e3+10;
	struct node{
		int to,lim,nxt;
	}e[M];
	int head[N],dep[N],cnt=1,n,m,d,S,T;
	inline void add1(int u,int v,int w)
	{
		e[++cnt].lim=w; e[cnt].nxt=head[u]; e[cnt].to=v;
		return head[u]=cnt,void();
	} 
	inline void add(int u,int v,int w){return add1(u,v,w),add1(v,u,0);}
	inline bool bfs()
	{
		queue<int> q;
		memset(dep,0,sizeof(dep)); dep[S]=1; q.push(S);
		while(!q.empty())
		{
			int fr=q.front(); q.pop();
			for(int i=head[fr];i;i=e[i].nxt)
			{
				int t=e[i].to; 
				if(e[i].lim&&!dep[t]) dep[t]=dep[fr]+1,q.push(t);
			}
		} return dep[T];
	} 
	inline int dfs(int now,int in)
	{
		if(now==T) return in; int out=0;
		for(int i=head[now];i;i=e[i].nxt)
		{
			int t=e[i].to; 
			if(e[i].lim&&dep[now]==dep[t]-1) 
			{
				int res=dfs(t,min(e[i].lim,in));
				in-=res; out+=res; e[i].lim-=res;
				e[i^1].lim+=res;
			}
		}if(!out) dep[now]=0;
		return out;
	}
	char s[N][N];
	inline int id1(int x,int y){return (x-1)*m+y;}
	inline int id2(int x,int y){return n*m+id1(x,y);}
	inline int dis(int a,int b,int c,int d){return (a-c)*(a-c)+(b-d)*(b-d);}
	signed main()
	{
		n=read(),m=read(),d=read();
		S=n*m*2+1,T=n*m*2+2;
		for(int i=1;i<=n;++i) 
		{
			for(int j=1;j<=m;++j)
			{
				cin>>s[i][j]; 
				if(s[i][j]>‘0‘) 
				{
					add(id1(i,j),id2(i,j),s[i][j]-‘0‘);
					if(i<=d||i>=n-d+1||j<=d||j>=m-d+1) 
					{
						add(id2(i,j),T,1e18+10);
					}
				}
			} 
		}
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=m;++j)
			{
				for(int k=1;k<=n;++k)
				{
					for(int l=1;l<=m;++l)
					{
						if(dis(i,j,k,l)<=d*d) add(id2(i,j),id1(k,l),1e18+10); 
					}
				}
			}
		}
		int num=0,ans=0;
		for(int i=1;i<=n;++i) 
		{
			for(int j=1;j<=m;++j) 
			{
				cin>>s[i][j]; 
				if(s[i][j]==‘L‘) 
				{
					num++;
					add(S,id1(i,j),1); 
				}
			}
		} 
		while(bfs()) ans+=dfs(S,1e18+10);
		cout<<num-ans<<endl;
		return 0;
	}
}
signed main(){return yspm::main();}

Luogu2472 SCOI2007蜥蜴

标签:etc   long   http   ref   最大   har   spm   ret   拆点   

原文地址:https://www.cnblogs.com/yspm/p/13070145.html

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