题解:CF1426E Rock, Paper, Scissors

CF1426E Rock, Paper, Scissors

思路

最多很好求,只需要贪心让石头尽可能多对剪刀,剪刀尽可能多对布,布尽可能多对石头即可。

最少的呢?我想了半小时没写出来。

于是:

\[\text{网 \ 络 \ 流} \]

建立二分图模型,将 \(S\) 与 Alice 的石头剪刀布连边,容量为数量,费用为 \(0\),将 Bob 的同理与 \(T\) 连边。

将 Alice 与 Bob 可能赢的组合连费用为 \(1\),容量无限大的边,反之连费用为 \(0\),容量无限大的边。

跑一遍费用流,于是不带一点脑子A了。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
namespace mf{
	const int N=405,INF=0x3f3f3f3f3f3f3f3f;
	struct node{int x,w,c,rev;};
	vector<node> t[N];
	int dis[N],flow[N],maxflow,mincost;
	node *pre[N];
	bool vis[N];
	int n,S,T;
	void init(int nn){
		memset(flow,0,sizeof(flow));
		for(int i=1;i<=nn+2;i++)
			t[i].clear();
		n=nn+2,S=nn+1,T=nn+2;
	}
	void add(int x,int y,int w,int c){
		t[x].push_back({y,w,c,t[y].size()});
		t[y].push_back({x,0,-c,t[x].size()-1});
	}
	bool spfa(){
		memset(dis,0x3f,sizeof(dis));
		memset(vis,0,sizeof(vis));
		queue<int> q;
		dis[S]=0,vis[S]=true,flow[S]=INF,q.push(S);
		while(!q.empty()){
			int u=q.front();
			q.pop(),vis[u]=false;
			for(node&v:t[u]){
				if(v.w&&dis[v.x]>dis[u]+v.c){
					dis[v.x]=dis[u]+v.c;
					flow[v.x]=min(flow[u],v.w);
					pre[v.x]=&v;
					if(!vis[v.x])
						vis[v.x]=true,q.push(v.x);
				}
			}
		}
		return dis[T]!=INF;
	}
	void upd(){
		int x=T;
		while(x!=S){
			node *i=pre[x];
			i->w-=flow[T];
			t[i->x][i->rev].w+=flow[T];
			x=t[i->x][i->rev].x;
		}
		maxflow+=flow[T],mincost+=flow[T]*dis[T];
	}
	pair<int,int> ek(){
		maxflow=mincost=0;
		while(spfa()) upd();
		return {maxflow,mincost};
	}
}
int n,a1,a2,a3,b1,b2,b3;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr),cout.tie(nullptr);
	cin>>n>>a1>>a2>>a3>>b1>>b2>>b3;
	mf::init(6);
	mf::add(mf::S,1,a1,0);
	mf::add(mf::S,2,a2,0);
	mf::add(mf::S,3,a3,0);
	mf::add(4,mf::T,b1,0);
	mf::add(5,mf::T,b2,0);
	mf::add(6,mf::T,b3,0);
	mf::add(1,4,mf::INF,0);
	mf::add(1,5,mf::INF,1);
	mf::add(1,6,mf::INF,0);
	mf::add(2,4,mf::INF,0);
	mf::add(2,5,mf::INF,0);
	mf::add(2,6,mf::INF,1);
	mf::add(3,4,mf::INF,1);
	mf::add(3,5,mf::INF,0);
	mf::add(3,6,mf::INF,0);
	cout<<mf::ek().second<<" "<<min(a1,b2)+min(a2,b3)+min(a3,b1)<<endl;
	return 0;
}
posted @ 2025-03-26 11:06  WuMin4  阅读(11)  评论(0)    收藏  举报