2024-8-20模拟赛T2

image

提交题目链接

题意:

\(n\) 个点,每个点有相应的权值,用 \(m\) 条边将点连接形成多个联通块,按某种顺序依次删除这 \(n\) 个点,求每次操作后,全部的连通块中总权值的最大值。

解析:

将依次删点变为依次加点,并在加点时用并查集维护权值,然后更新最大权值。

插嘴:

看似简单的题其实有许多坑,像我考试时就没有思路,听到讲解才发现其实这题我做过类似的(菜),然后根据解析调代码时还调不出。

跟着代码学学吧!!只要脑子不抽其实这题很简单的!! 我好菜

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+10;
int n,m;
int fa[N];
vector<int> v[N];
ll val[N]; 
int z[N];
ll jg[N];
int pre[N];
int find(int x){
	if(fa[x]==x){
		return x;
	}
	return fa[x]=find(fa[x]);
}

int main(){
	freopen("qd.in","r",stdin);
	freopen("qd.out","w",stdout);
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		fa[i]=i;
		cin>>val[i];
	}
	
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);	
	}
	
	int x;
	ll ans=0;
	
	stack<int> r;
	
	for(int i=1;i<=n;i++){
		cin>>pre[i]; 
	}
	
	for(int i=n;i>=2;i--){
		x=pre[i];
		z[x]=1;
		
		for(int i=0;i<v[x].size();i++){
			if(z[v[x][i]]==1){
				if(find(v[x][i])!=find(x)){
					int xx=find(x),yy=find(v[x][i]);
					
					fa[yy]=fa[xx];
					val[xx]+=val[yy];
					
				}
			}
		}
		ans=max(ans,val[find(x)]);
		jg[i-1]=ans;
	}
	
	for(int i=1;i<=n;i++){
		cout<<jg[i]<<"\n";
	}
	
	return 0;
} 
/*
6 7
1 1 4 5 1 4
1 2
3 4
4 5
5 6
3 6
3 5
4 6
4 5 3 6 1 2
*/ 
posted @ 2024-08-21 15:26  sad_lin  阅读(15)  评论(0)    收藏  举报