CF Round #529 (Div. 3) F

版权声明:copy right https://blog.csdn.net/qq_43521140/article/details/90542930

Source
题目大意:
给你n个点,以及每个点的权值ai。连接任意两点之间的花费为ax + ay。
另给出额外m条边的花费,问你要使n个点连通的最少总花费。

思路:
我们容易发现,在不考虑额外给出的m条特殊边的情况下,原图的最少总花费方案为每一个点都向权值最小顶点连一条边。而此题我们只需要再将m条额外边加入边集,对共有(n-1)+ m 条边的边集使用最小生成树算法即可求解。

ACODE:

//7777777
#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<set>
#include<queue>
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const double eps = 1e-5;
const int MXN = 1e2 + 7;
const int MXM = 1e4 + 7;
const int MX = 2e5 + 7;
const int maxbit = 18;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int pre[MX];
int n,m;
struct chr1s
{
	int id;
	ll v;
	inline bool operator <(const chr1s & x){
		return v < x.v;
	}
}val[MX << 1];
struct node
{
	int u,v;
	ll w;
}e[MX << 1];
void init()
{
	for(int i = 1;i <= n;++i)
	{
		pre[i] = i;
	}
}
int find(int x)
{
	if(pre[x] == x) return x;
	return pre[x] = find(pre[x]);
}
bool same(int x,int y)
{
	return find(x) == find(y);
}
void unionset(int x,int y)
{
	int f1 = find(x);
	int f2 = find(y);
	if(f1 == f2) return ;
	pre[f1] = f2;
}
bool cmp(node a,node b)
{
	return a.w < b.w;
}
ll kruskal()
{
	int cont = 0;
	ll ans = 0;
	init();
	sort(e+1,e+1+m,cmp);
	for(int i = 1;i <= m;++i){
		if(same(e[i].u,e[i].v)) continue;
		unionset(e[i].u,e[i].v);
		ans += e[i].w;
		cont++;
		if(cont == n-1) break;
	}
	return ans;
}
int main()
{
	#ifdef local
        freopen("Input_File.txt","r",stdin);
        freopen("Output_File.txt","w",stdout);
	#endif
    cin >> n >> m;
    for(int i = 1;i <= n;++i)
    {
    	cin >> val[i].v;
    	val[i].id = i;
    }
    for(int i = 1;i <= m;++i){
    	cin >> e[i].u >> e[i].v >> e[i].w;
    }
    sort(val+1,val+1+n);
    for(int i = 2;i <= n;++i){
    	e[++m].u = val[1].id;
    	e[m].v = val[i].id;
    	e[m].w = val[1].v + val[i].v;
    }
    ll ans = kruskal();
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43521140/article/details/90542930
今日推荐