HDU-2732 Leapin' Lizards split point maximum flow + BFS learn English QAQ

Topic link

https://vjudge.net/problem/HDU-2732

Title

An n*m matrix, there are some squares on the matrix, some people are on the squares, the jumping distance of the person is d, and the Manhattan distance (abs (row difference) + abs (column difference)) is less than or equal to d On the other box. Jumping out of the maze is regarded as an escape. Each square has a jumping limit a, and a maximum of a jump is allowed (jumping from this square to other squares reduces by one). I asked how many people could not escape.

Ideas

All the squares are split into in and out. In is connected to out, and the right is the jump limit. s connects edges to a human square, and the weight is 1. Do bfs for each square i. For box j that can be reached within d steps, connect the out of i to in of j, and the weight is limited (in fact, larger than the limit Any number will do). In the process of bfs, judge whether you can jump out of the map. If possible, connect the out of this box to t, the right is the limit, run the maximum flow, and the answer is the total number of people-the maximum flow.

Pay attention to the output, no and 1 correspond to not adding s and was, and 2 and above correspond to adding s and were. This broken place wa several times and I have served myself.

Code

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib> 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
using namespace std;
	typedef long long ll;
	const int inf=0x3f3f3f3f;
	const int maxn=2020;
	const int maxe=200010;
	//前向星部分 
	int head[maxn],cnt; 
	struct Edge{
    
    
		int v;
		int w;
		int next;
	}edge[maxe];
	
	//用于BFS 
	struct Node{
    
    
		int x,y,z;
	}node;
	//Dinic部分 
	int n,m,d,s,t,tot;
	ll maxflow;
	int deep[maxn];
	int now[maxe];
	//BFS部分 
	bool inq[30][30];	
	int dxy[][2]={
    
    {
    
    1,0},{
    
    -1,0},{
    
    0,1},{
    
    0,-1}};
	//迷宫情况 
	int gp[30][30];
	bool gp2[30][30];
	//总初始化 
	void init(){
    
    
		tot=0;
		memset(head,-1,sizeof(head));
		memset(gp,0,sizeof gp);
		memset(gp2,0,sizeof gp2);
		cnt=0;
		maxflow=0; 
		return ;	
	}
	//前向星加边 
	void add(int u,int v,int w){
    
    
		//if(v==t)
		//cout<<u<<" "<<v<<" "<<w<<endl;
  		edge[cnt].v=v;
		edge[cnt].w=w;
		edge[cnt].next=head[u];
		head[u]=cnt++;
	}
	//Dinic 
	inline bool bfs(){
    
    
    	memset(deep,0x3f,sizeof(deep));
    	queue<int>q;
    	q.push(s);deep[s] = 0;now[s] = head[s];
    	while(q.size()){
    
    
        	int x = q.front();q.pop();
        	for(int i=head[x];i!=-1;i=edge[i].next){
    
    
        	    int y=edge[i].v;
         	    if(edge[i].w>0&&deep[y]==inf){
    
    
         	    	q.push(y);
        	        now[y]=head[y];
         	       	deep[y]=deep[x]+1;
        	        if(y==t)	return 1;
				}
        	}
    	}
    	return 0;
	}

	ll dfs(int x,int flow){
    
    
    	if(x==t)	return flow;
    	ll ans = 0,k,i;
    	for(i=now[x];i!=-1&&flow;i=edge[i].next){
    
    
        	now[x]=i;
        	int y=edge[i].v;
        	if(edge[i].w>0&&(deep[y]==deep[x]+1)){
    
    
        	    k=dfs(y,min(flow,edge[i].w));
         		if(!k)	deep[y]=inf;
            	edge[i].w-=k;
            	edge[i^1].w+=k;
            	ans+=k;
            	flow-=k;
        	}
    	}
    	return ans;
	}	

	void dinic(){
    
    
    	while(bfs())
    	    maxflow+=dfs(s,inf);
	}
	//BFS部分 
	void find(int x,int y){
    
    
		memset(inq,0,sizeof inq);
		//拆点连边 
		add((x-1)*m+y,(x-1)*m+y+500,gp[x][y]);
		add((x-1)*m+y+500,(x-1)*m+y,0);
		queue<Node>q;
		q.push({
    
    x,y,0});
		inq[x][y]=1;
		//这个方块能否跳出迷宫 
		bool es=0;
		while(q.size()){
    
    
			node=q.front(),q.pop();
			if(node.z>d)
				continue;
			//方块i向j连边 
			if(gp[node.x][node.y]){
    
    
				add((x-1)*m+y+500,(node.x-1)*m+node.y,gp[x][y]);
				add((node.x-1)*m+node.y,(x-1)*m+y+500,0);
			}
			//四方向遍历 
			for(int i=0;i<4;i++){
    
    
				int xx=node.x+dxy[i][0],yy=node.y+dxy[i][1];
				if((xx<1||xx>n||yy<1||yy>m)&&node.z<d)
					es=1;//可以跳出 
				else if(inq[xx][yy]==0){
    
    
					inq[xx][yy]=1;
					q.push({
    
    xx,yy,node.z+1});
				}
			}
		}
		//可以跳出就向t连边 
		if(es){
    
    	
			add((x-1)*m+y+500,t,gp[x][y]);
			add(t,(x-1)*m+y+500,0);
		}
		
	}
	int main(){
    
    	
		int tn;
		scanf("%d\n",&tn);
		for(int _=1;_<=tn;_++){
    
    
			init();
			//输入处理 
			scanf("%d%d",&n,&d);
			getchar();
			m=1;
			char ch;
			ch=getchar();
			while(ch!='\n'){
    
    
				gp[1][m]=ch-'0';
				ch=getchar();
				m++;
			}
			m--;
			for(int i=2;i<=n;i++){
    
    
				for(int j=1;j<=m;j++){
    
    
					ch=getchar();
					gp[i][j]=ch-'0';
				}
				getchar();
			} 
			for(int i=1;i<=n;i++){
    
    
				for(int j=1;j<=m;j++){
    
    
					ch=getchar();
					if(ch=='L'){
    
    
						tot++;
						gp2[i][j]=1;
					}
				}
				getchar();
			}
			//s和t设成绝对不可能编号的点 
			s=1501,t=s+1;
			//1---n*m是方块in,501---n*m+500是方块out 
			//s向有人的块的in连边 
			for(int i=1;i<=n;i++){
    
    
				for(int j=1;j<=m;j++){
    
    
					if(gp2[i][j]){
    
    
						add(s,(i-1)*m+j,1);
						add((i-1)*m+j,s,0);
					}
				}
			}
			//对每个可以跳的方块跑bfs,in-out连边部分也放在了里面 
			for(int i=1;i<=n;i++){
    
    
				for(int j=1;j<=m;j++){
    
    
					if(gp[i][j]){
    
    
						find(i,j);
					}
				}
			}
			dinic();
			int ans=tot-maxflow;
			//输出一定仔细,除了名词单复数还有was和were的区别。 
			printf("Case #%d: ",_);
			if(!ans)
				printf("no lizard was left behind.\n");
			else if(ans==1)
				printf("1 lizard was left behind.\n");
			else
				printf("%d lizards were left behind.\n",ans);
		}
    	return 0;
	}

Guess you like

Origin blog.csdn.net/TheSunspot/article/details/108351188