Logan-P2472 [SCOI2007] Lagarto (flujo máximo)

Enlace de tema: haga clic para ver

La idea principal del tema: Dado un laberinto de n * m, cada posición tiene una durabilidad, es decir, después de pasar una posición [i] [j] (i, j) como máximo, ahora hay algunas lagartijas en el laberinto. Hay como máximo un lagarto en cada posición, y cada lagarto puede saltar a la cuadrícula donde la distancia euclidiana no excede d cada vez. El límite del laberinto es la salida. Pregunte al menos cuántos lagartos no pueden escapar del laberinto.

Análisis de problemas: en caso de problemas, puede repasar el problema del agua. . Siempre siento que esta pregunta se hizo hace mucho tiempo, tal vez se hizo en un sueño.

Cuántas lagartijas no pueden escapar al menos -> Cuántas lagartijas pueden escapar como máximo

Cada ubicación tiene una capacidad, por lo que el límite de corriente del punto de división

Así que salió mal el modelo:

  1. Punto de origen -> la ubicación de cada lagarto, el caudal es 1
  2. El punto de entrada de cada punto -> el punto de salida de cada punto, el flujo es un [i] [j]
  3. El punto de salida de cada punto -> el punto de entrada del punto cuya distancia euclidiana no excede d, el flujo es inf
  4. El punto de salida de cada punto -> el límite del laberinto (si se puede alcanzar), el caudal es inf

La respuesta es el número total de lagartijas menos la respuesta al flujo máximo.

Cabe señalar que al principio, la distancia euclidiana se consideró como la distancia de Manhattan, y se obtuvieron inexplicablemente 90 puntos.

Además, para cada punto, debe conectar un borde con el flujo de inf desde su punto de salida hasta su punto de entrada, lo que significa que un cierto lagarto permanece quieto en su posición actual (porque el título no dice que cada lagarto tiene una tasa de flujo de inf). Debes moverte en todo momento, así que al mismo tiempo, mantén un lagarto en movimiento)

Código:
 

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
     
typedef long long LL;
     
typedef unsigned long long ull;
     
const int inf=0x3f3f3f3f;

const int N=1e6+100;
 
struct Edge
{
	int to,w,next;
}edge[N];//边数
 
int head[N],cnt,n,m,id1[25][25],id2[25][25];

char s[N];
 
void addedge(int u,int v,int w)
{
	edge[cnt].to=v;
	edge[cnt].w=w;
	edge[cnt].next=head[u];
	head[u]=cnt++;
	edge[cnt].to=u;
	edge[cnt].w=0;//反向边边权设置为0
	edge[cnt].next=head[v];
	head[v]=cnt++;
}
 
int d[N],now[N];//深度 当前弧优化
 
bool bfs(int s,int t)//寻找增广路
{
	memset(d,0,sizeof(d));
	queue<int>q;
	q.push(s);
	now[s]=head[s];
	d[s]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=edge[i].next)
		{
			int v=edge[i].to;
			int w=edge[i].w;
			if(d[v])
				continue;
			if(!w)
				continue;
			d[v]=d[u]+1;
			now[v]=head[v];
			q.push(v);
			if(v==t)
				return true;
		}
	}
	return false;
}
 
int dinic(int x,int t,int flow)//更新答案
{
	if(x==t)
		return flow;
	int rest=flow,i;
	for(i=now[x];i!=-1&&rest;i=edge[i].next)
	{
		int v=edge[i].to;
		int w=edge[i].w;
		if(w&&d[v]==d[x]+1)
		{
			int k=dinic(v,t,min(rest,w));
			if(!k)
				d[v]=0;
			edge[i].w-=k;
			edge[i^1].w+=k;
			rest-=k;
		}
	}
	now[x]=i;
	return flow-rest;
}
 
void init()
{
    memset(now,0,sizeof(now));
	memset(head,-1,sizeof(head));
	cnt=0;
}
 
int solve(int st,int ed)
{
	int ans=0,flow;
	while(bfs(st,ed))
		while(flow=dinic(st,ed,inf))
			ans+=flow;
	return ans;
}

void get_id()
{
	int id=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			id1[i][j]=++id;
			id2[i][j]=++id;
		}
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	init();
	int d,st=N-1,ed=st-1;
	scanf("%d%d%d",&n,&m,&d);
	get_id();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			int num;
			scanf("%1d",&num);
			addedge(id1[i][j],id2[i][j],num);
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int dx=-4;dx<=4;dx++)
				for(int dy=-4;dy<=4;dy++)
					if(dx*dx+dy*dy<=d*d)
					{
						int xx=dx+i,yy=dy+j;
						if(xx<=0||yy<=0||xx>n||yy>m)
							addedge(id2[i][j],ed,inf);
						else
							addedge(id2[i][j],id1[xx][yy],inf);
					}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
			if(s[j]=='L')
			{
				ans++;
				addedge(st,id1[i][j],1);
			}
	}
	printf("%d\n",ans-solve(st,ed));




    return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/qq_45458915/article/details/109125781
Recomendado
Clasificación