专栏文章

2025 CSP-S

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min30ua5
此快照首次捕获于
2025/12/01 19:44
3 个月前
此快照最后确认于
2025/12/01 19:44
3 个月前
查看原文

2025 CSP-S

T1T2T3T4

T1 [CSP-S 2025] 社团招新 / club

题意:

nn个人分到3个部门,每个部门人数不能超过n2\frac{n}{2},求满意值最大可以为多少?

思路:

先将每个人分到其最满意的部门,再把人数超过n2 \frac{n}{2}人的部门人数减到n2 \frac{n}{2}人,因为不可能同时有两个部门超过n2 \frac{n}{2}人,对于要移除到其他部门的则使其最大满意值与次大满意值差最小

代码:

CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N(1e5+10);
int n,ans(0);
struct node{
	int a,b,c;
	int maxx,next;
}e[N];
vector<int>x,y,z,sc;
void solve(){
	cin>>n;
	ans=0;
	x.clear();y.clear();
	z.clear();sc.clear();
	for(int i(1);i<=n;i++){
		cin>>e[i].a>>e[i].b>>e[i].c;
		e[i].maxx=max(e[i].a,max(e[i].b,e[i].c));
		ans+=e[i].maxx;
		if(e[i].maxx==e[i].a){
			x.push_back(i);
			e[i].next=max(e[i].b,e[i].c);
		}
		if(e[i].maxx==e[i].b){
			y.push_back(i);
			e[i].next=max(e[i].a,e[i].c);
		}
		if(e[i].maxx==e[i].c){
			z.push_back(i);
			e[i].next=max(e[i].b,e[i].a);
		}
	}
	int siz(max(x.size(),max(y.size(),z.size())));
	if(siz>n/2){
		if(siz==x.size()){
			for(int i(0);i<siz;i++){
				sc.push_back(e[x[i]].maxx-e[x[i]].next);
			}
		}
		if(siz==y.size()){
			for(int i(0);i<siz;i++){
				sc.push_back(e[y[i]].maxx-e[y[i]].next);
			}
		}
		if(siz==z.size()){
			for(int i(0);i<siz;i++){
				sc.push_back(e[z[i]].maxx-e[z[i]].next);
			}
		}
	}
	sort(sc.begin(),sc.end());
	for(int i(0);sc.size()>n/2&&i<sc.size()-n/2;i++){
		ans-=sc[i];
	}
	cout<<ans<<'\n';
}
int main(){
	int T;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

T2 [CSP-S 2025] 道路修复 / road

题意:

n个城市,m条路,k个乡村,修条路要钱,将乡村升级要钱,在升级后的乡村到城市之间建路也要钱,最少要多少钱才能把n个城市都连接起来?

思路:

  1. 先把不是最小生成树上的边都剪掉(此最小生成树仅考虑m条边
  2. 使用二进制枚举每个乡村建不建,如果建就把可以建的路都放到队列里去,再跑一遍最小生成树

代码:

CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N(1e5+10);
ll n,m,k;
ll ans(1e18+7);
ll f[N],cost[15];
bool vis[15];
struct node{
	ll u,v,w;
};
vector<node>e,ee;
ll find(ll x){
	if(f[x]==x){
		return x;
	}
	return f[x]=find(f[x]);
}
bool cmp(node a,node b){
	return a.w<b.w;
}
int main(){
	cin>>n>>m>>k;
	// cout<<n<<'\n';
	for(ll i(1);i<=n;i++){
		f[i]=i;
	}
	for(ll i(1);i<=m;i++){
		ll u,v,w;
		cin>>u>>v>>w;
		ee.push_back({u,v,w});
	}
	sort(ee.begin(),ee.end(),cmp);
	ll tot(0);
	for(ll i(1);i<=m&&tot!=n-1;i++){
		ll u(find(ee[i].u)),v(find(ee[i].v));
		if(u!=v){
			f[v]=u;
			tot++;
			e.push_back(ee[i]);
		}
	}
	for(ll i(1);i<=k;i++){
		ll c;
		cin>>c;
		cost[i]=c;
		for(ll j(1);j<=n;j++){
			ll w;
			cin>>w;
			e.push_back({j,n+i,w});
		}
	}
	sort(e.begin(),e.end(),cmp);
	for(ll stat(0);stat<(1<<k);stat++){
		ll now(0);
		ll num(0);
		for(ll i(1);i<=k;i++){
			if((stat>>(i-1))&1){
				num++;
				vis[i]=true;
				now+=cost[i];
			}else{
				vis[i]=false;
			}
		}
		for(ll i(1);i<=n+k;i++){
			f[i]=i;
		}
		ll need(n+num-1);
		for(ll i(0);i<e.size();i++){
			ll u(e[i].u),v(e[i].v);
			if(v>n&&!vis[v-n]){
				continue;
			}
			ll fu(find(u)),fv(find(v));
			if(fu!=fv){
				f[fv]=fu;
				now+=e[i].w;
				if(!(--need)){
					break;
				}
			}
		}
		if(!need){
			ans=min(ans,now);
		}
	}
	cout<<ans<<'\n';
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...