样例TLE求助
查看原帖
样例TLE求助
1121412
Cute_Fish楼主2023/12/16 12:49

rt

//EK是从板子题复制过来的……
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
#define hh puts("")
const int inf=9e18;
const int N=5e4+7;
int n,m,l,s,t,cnt=-1,head[N],nw[N];
int flow[N],pre[N],d[N],vis[N];
int x[N],y[N];
struct edge{
	int from,to,next,flow,dis;
}e[N<<1];
inline void add_(int from,int to,int flow,int dis){
    e[++cnt]={from,to,head[from],flow,dis};
	head[from]=cnt;
}
inline void add(int u,int v,int flow,int dis){
	add_(u,v,flow,dis);
	add_(v,u,0,-dis);
}
inline int id(int x,int y){return (x-1)*m+y;}
inline bool spfa(int s,int t){
	memset(d,0x7f,sizeof(d));
	memset(flow,0x7f,sizeof(flow));
	memset(vis,0,sizeof(vis));
	queue<int>q;
	vis[s]=1,q.push(s);
	d[s]=0,pre[t]=-1;
	while(!q.empty()){
		int u=q.front();q.pop();
		vis[u]=0;
		for(int i=head[u];~i;i=e[i].next){
			edge v=e[i];
			if(v.flow&&d[v.to]>d[u]+v.dis){
				d[v.to]=d[u]+v.dis;
				pre[v.to]=u;
				nw[v.to]=i;
				flow[v.to]=min(flow[u],v.flow);
				if(!vis[v.to]){
					vis[v.to]=1;
					q.push(v.to);
				}
			}
		}
	}
	return pre[t]!=-1;
}
inline int EK(int s,int t){
	int maxflow=0,mindis=0;
	while(spfa(s,t)){
		int u=t;
		maxflow+=flow[t];
		mindis+=flow[t]*d[t];
		while(u!=s){
			e[nw[u]].flow-=flow[t];
			e[nw[u]^1].flow+=flow[t];
			u=pre[u];
		}
	}
	return maxflow;
}
inline int AKIOI(int x1,int y1,int x2,int y2){
	return abs(x1-x2)*abs(x1-x2)+abs(y1-y2)*abs(y1-y2);
}
signed main(){
	int tot=0;
	cin>>n>>m>>l;
	s=0,t=2*n*m+1;//源点汇点
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char ch;cin>>ch;
			int dis=ch-'0';
			add(id(i,j),id(i,j)+n*m,dis,0);
          //拆点分成入点和出点,连一题容量为石柱高度的边
			if(dis){
				x[id(i,j)]=i,y[id(i,j)]=j;//记录坐标
			    if(i+l>n||j+l>m||i-l<1||j-l<1)add(id(i,j)+n*m,t,inf,0);//可以直接跳出去,出点连向汇点
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char ch;cin>>ch;
			if(ch=='L'){
				add(s,id(i,j),inf,0);//源点连向蜥蜴的入点
				tot++;//记录蜥蜴个数
			}
		}
	}
	for(int i=1;i<=n*m;i++){
		for(int j=1;j<=n*m;j++){
			if(i==j)continue;
			if(AKIOI(x[i],y[i],x[j],y[j])<=l*l)add(id(x[i],y[i])+n*m,id(x[j],y[j]),inf,0);
          //判断是否可以跳过去,如果可以连一条边
		}
	}
	cout<<tot-EK(s,t)<<"\n";//蜥蜴数-最大流
} 
2023/12/16 12:49
加载中...