2020杭州電気マルチスクール第2セッションA複合チェック+変換

ここに画像の説明を挿入
タイトルによって、要件を完了するための最小数の操作を見つけることができます。もちろん、グラフは常に最小点から分割できますが、これは特に低速です。
したがって、考えを変えて、すべてのポイントの重みを最初に合計することができます。この場合、繰り返しがあることがわかっているので、小さいものから大きいものに変換し、大きいものから小さいものへトラバースします。各ノードに到達すると、現在のノードに接続されたポイントを検索します。接続されたポイントが以前にトラバースされ、それらが同じセット内にない場合、現在の位置でのポイントの重みが繰り返され、減算されてから配置されますそれをコレクションに入れます(そしてコレクションをチェックして完了します)。この方法でトラバーサルを完了した後、残りの重量合計が必要な答えです。

コード:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 2e6+7;
vector<int>G[MAXN];
int n,m;
ll w[MAXN];
int pre[MAXN];
int vis[MAXN];
struct node
{
    
    
	ll w;
	int id;
}point[MAXN];

bool cmp(node a,node b){
    
    
	return a.w > b.w;
}

int Find(int x)
{
    
    
	if(pre[x] == x) return x;
	else return pre[x] = Find(pre[x]);
}

int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--){
    
    
		ll ans = 0;
		scanf("%d%d",&n,&m);
		for(int i = 1;i <= n;i ++){
    
    
			pre[i] = i;
			vis[i] = 0;
			G[i].clear();
		}
		for(int i = 1;i <= n;i ++){
    
    
			scanf("%lld",&w[i]);
			point[i].w = w[i],point[i].id = i;
			ans += point[i].w;
		}
		while(m--){
    
    
			int u,v;
			scanf("%d%d",&u,&v);
			G[u].push_back(v);
			G[v].push_back(u);
		}
		//for(int i = 1;i <= n;i ++){
    
    
			//for(int j = 0;j < G[i].size();j ++) printf("---%d to is %d\n",i,G[i][j]);
		//}
		sort(point+1,point+1+n,cmp);
		//for(int i = 1;i <= n;i ++) printf("%d %d\n",point[i].id,point[i].w);
		for(int i = 1;i <= n;i ++){
    
    
			for(auto to : G[point[i].id]){
    
    
				if(vis[to]){
    
    
					int a = Find(point[i].id),b = Find(to);
					if(a != b){
    
    
						pre[b] = a;
						ans -= w[point[i].id];
					}
				}
				vis[point[i].id] = 1;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/weixin_45672411/article/details/108321841