CF704D Captain America 题解

考虑如果没有限制,那么我们肯定全为\(r\)或者全为\(b\),然后在有限制的情况下,花费小的越多越好,就是一个上下界有源汇最大流的板子题目了。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
const int maxn=1e5+10;
const int MX=4e5+10;
const int mxn=6e6+10;
int n,m,r,b,x[maxn],y[maxn],ge,li1[maxn],s,t,cnt1,cnt2,li2[maxn],lin1,lin2,lin3;
int cx[maxn],cy[maxn],lmx[maxn],lmy[maxn],lin,tot=1,head[MX],nxt[mxn],to[mxn];
int cap[mxn],xj,sj,sum,S,T,d[MX],ans,cnt[MX],vis[MX],cur[MX];
void add(int q,int w,int qw){
	tot++;
	nxt[tot]=head[q];
	head[q]=tot;
	to[tot]=w;
	cap[tot]=qw;
	tot++;
	nxt[tot]=head[w];
	head[w]=tot;
	to[tot]=q;
	return;
}
int spfa(){
	for(int i=1;i<=ge;i++){
		cnt[i]=inf;
		vis[i]=0;
		cur[i]=head[i];
	}
	queue<int>Q;
	Q.push(S);
	cnt[S]=0;
	while(!Q.empty()){
		int now=Q.front();
		Q.pop();
		if(vis[now]){
			continue;
		}
		vis[now]=1;
		for(int i=head[now];i;i=nxt[i]){
			if(cnt[to[i]]>cnt[now]+1&&cap[i]){
				cnt[to[i]]=cnt[now]+1;
				Q.push(to[i]);
			}
		}
	}
	if(cnt[T]!=inf){
		return 1;
	}
	return 0;
}
int dfs(int q,int w){
	if(q==T){
		return w;
	}
	int sum=0;
	for(int i=cur[q];i;i=nxt[i]){
		cur[q]=i;
		if(cnt[to[i]]==cnt[q]+1&&cap[i]){
			int flow=dfs(to[i],min(cap[i],w));
			if(flow){
				cap[i]-=flow;
				cap[i^1]+=flow;
				sum+=flow;
				w-=flow;
				if(!w){
					return sum;
				}
			}
		}
	}
	return sum;
}
int dinic(){
	int ss=0;
	while(spfa()){
		ss+=dfs(S,inf);
	}
	return ss;
}
void init(){
	cin>>n>>m>>r>>b;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>y[i];
	}
	cnt1=0;
	for(int i=1;i<=n;i++){
		cnt1++;
		li1[cnt1]=x[i];
	}
	sort(li1+1,li1+1+cnt1);
	cnt1=unique(li1+1,li1+1+cnt1)-li1-1;
	for(int i=1;i<=n;i++){
		x[i]=lower_bound(li1+1,li1+1+cnt1,x[i])-li1;
		cx[x[i]]++;
	}
	for(int i=1;i<=cnt1;i++){
		lmx[i]=cx[i];
	}
	cnt2=0;
	for(int i=1;i<=n;i++){
		cnt2++;
		li2[cnt2]=y[i];
	}
	sort(li2+1,li2+1+cnt2);
	cnt2=unique(li2+1,li2+1+cnt2)-li2-1;
	for(int i=1;i<=n;i++){
		y[i]=lower_bound(li2+1,li2+1+cnt2,y[i])-li2;
		cy[y[i]]++;
	}
	for(int i=1;i<=cnt2;i++){
		lmy[i]=cy[i];
	}
	ge=cnt1+cnt2;
	ge++;
	s=ge;
	ge++;
	t=ge;
	ge++;
	S=ge;
	ge++;
	T=ge;
	for(int i=1;i<=n;i++){
		add(x[i],y[i]+cnt1,1);
	}
	for(int i=1;i<=m;i++){
		cin>>lin1>>lin2>>lin3;
		if(lin1==1){
			lin=lower_bound(li1+1,li1+1+cnt1,lin2)-li1;
			if(lin2!=li1[lin]){
				continue;
			}
			lmx[lin]=min(lmx[lin],lin3);
		}
		else{
			lin=lower_bound(li2+1,li2+1+cnt2,lin2)-li2;
			if(lin2!=li2[lin]){
				continue;
			}
			lmy[lin]=min(lmy[lin],lin3);
		}
	}
	for(int i=1;i<=cnt1;i++){
		xj=(cx[i]-lmx[i]+1)/2;
		sj=(cx[i]+lmx[i])/2;
		if(xj>sj){
			cout<<-1;
			exit(0);
		}
		else{
			if(sj-xj)add(s,i,sj-xj);
			d[s]-=xj;
			d[i]+=xj;
		}
	}
	for(int i=1;i<=cnt2;i++){
		xj=(cy[i]-lmy[i]+1)/2;
		sj=(cy[i]+lmy[i])/2;
		if(xj>sj){
			cout<<-1;
			exit(0);
		}
		else{
			if(sj-xj)add(i+cnt1,t,sj-xj);
			d[i+cnt1]-=xj;
			d[t]+=xj;
		}
	}
	for(int i=1;i<=ge;i++){
		if(d[i]<0){
			add(i,T,-d[i]);
		}
		if(d[i]>0){
			add(S,i,d[i]);
			sum+=d[i];
		}
	}
	add(t,s,inf);
	return;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	init();
	if(dinic()!=sum){
		cout<<-1;
		return 0;
	}
	S=s;
	T=t;
	ans=dinic();
	cout<<1ll*ans*min(r,b)+1ll*(n-ans)*max(r,b)<<'\n';
	for(int i=1;i<=n;i++){
		if(cap[i*2]&&r<b){
			cout<<"b";
		}
		else if(cap[i*2]==0&&b<r){
			cout<<"b";
		}
		else{
			cout<<"r";
		}
	}
	return 0;
}
posted @ 2025-06-01 09:40  特别之处  阅读(6)  评论(0)    收藏  举报