染色+拆点网络流dinic 50pts求调
查看原帖
染色+拆点网络流dinic 50pts求调
993065
nnn233楼主2024/9/13 18:14
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+50,M=1e7+50,inf=1e15,L=10000000;
#define int long long
struct edge{
	int v,w,nex;
}e[M<<1];
int fir[N],cnt=1;
void add(int u,int v,int w){
	cnt++,e[cnt]={v,w,fir[u]},fir[u]=cnt;
	cnt++,e[cnt]={u,0,fir[v]},fir[v]=cnt;
}
int s,t,r,c,d,n,m,ans,cur[N],dis[N];
bool bfs(){
	queue<int> q;
	while(!q.empty())q.pop();
	for(int i=1;i<=2*m+2;i++)cur[i]=fir[i],dis[i]=0;
	q.push(s);dis[s]=1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=fir[u];i;i=e[i].nex){
			if(e[i].w&&!dis[e[i].v]){
				dis[e[i].v]=dis[u]+1;
				if(e[i].v==t)return 1;
				q.push(e[i].v); 
			}
		}
	}
	return 0;
}
int dfs(int u,int flow){ 
	if(u==t)return flow;
	int sum=0;
	for(int &i=cur[u];i;i=e[i].nex){
		if(dis[e[i].v]==dis[u]+1&&e[i].w){
			int tmp=dfs(e[i].v,min(flow,e[i].w));
			if(tmp){
				e[i].w-=tmp;
				e[i^1].w+=tmp;
				sum+=tmp;
				flow-=tmp;
				if(!flow){
					return sum; 
				}
			}else dis[e[i].v]=-1;
		}
	}
	return sum;
}
map<int,int> id;
signed main(){
	cin>>c>>r>>m;
	id.clear();
	s=m*2+1;//超级源点 
	t=m*2+2;//超级汇点 
	for(int i=1;i<=m;i++){
		int x,y,val;
		cin>>x>>y>>val;
		id[y*L+x]=i;//用map记录坐标 
		add(i,i+m,val);//拆点 
		if(y%2==1){
			if(x%4==0)add(s,i,inf);//超级源连边 
			if(x%4==3)add(i+m,t,inf);//超级汇连边
		}else{
			if(x%4==1)add(s,i,inf);//超级源连边 
			if(x%4==2)add(i+m,t,inf);//超级汇连边 
		}
	}
	for(int i=1;i<=r;i++){
		if(i%2==1){
			for(int j=1;j<=c;j+=4){
				if(id.count(i*L+j)!=0&&id.count(i*L+j+1)!=0){//枚举关键边 
					add(id[i*L+j]+m,id[i*L+j+1],inf);//关键边两侧点连
					//从关键边左侧点的上下左三个点向关键边左侧点连边 
					if(id.count((i-1) *L+ j  )!=0)add(id[(i-1) *L+ j  ]+m,id[i     *L+ j  ],inf);
					if(id.count((i+1) *L+ j  )!=0)add(id[(i+1) *L+ j  ]+m,id[i     *L+ j  ],inf);
					if(id.count(i     *L+ j-1)!=0)add(id[i     *L+ j-1]+m,id[i     *L+ j  ],inf);
					//从关键边右侧点向关键边右侧点上下右三个点连边
					if(id.count((i-1) *L+ j+1)!=0)add(id[i     *L+ j+1]+m,id[(i-1) *L+ j+1],inf);
					if(id.count((i+1) *L+ j+1)!=0)add(id[i     *L+ j+1]+m,id[(i+1) *L+ j+1],inf);
					if(id.count(i     *L+ j+2)!=0)add(id[i     *L+ j+1]+m,id[i     *L+ j+2],inf);
				}
			}
		}else{
			for(int j=4;j<=c;j+=4){
				if(id.count(i*L+j)!=0&&id.count(i*L+j-1)!=0){//枚举关键边 
					add(id[i*L+j]+m,id[i*L+j-1],inf);//关键边两侧点连
					//从关键边右侧点的上下右三个点向关键边右侧点连边
					if(id.count((i-1) *L+ j  )!=0)add(id[(i-1) *L+ j  ]+m,id[i     *L+ j  ],inf);
					if(id.count((i+1) *L+ j  )!=0)add(id[(i+1) *L+ j  ]+m,id[i     *L+ j  ],inf);
					if(id.count(i     *L+ j+1)!=0)add(id[i     *L+ j+1]+m,id[i     *L+ j  ],inf);
					//从关键边左侧点向关键边左侧点的上下左三个点连边
					if(id.count((i-1) *L+ j-1)!=0)add(id[i     *L+ j-1]+m,id[(i-1) *L+ j-1],inf);
					if(id.count((i+1) *L+ j-1)!=0)add(id[i     *L+ j-1]+m,id[(i-1) *L+ j-1],inf);
					if(id.count(i     *L+ j-2)!=0)add(id[i     *L+ j-1]+m,id[i     *L+ j-2],inf);
				}
			}
		}
	}
	while(bfs())ans+=dfs(s,inf);//dinic 
	cout<<ans; 
	return 0;
}
2024/9/13 18:14
加载中...