标签:洛谷 fu fv int 题解 fa P2700 find define
\(P2700\) 逐个击破
前置知识
克鲁斯卡尔最小生成树算法 并查集 贪心思想
题目描述
给出一颗带权的树,删除任意条边,求出使得给定的点不连通的最小权值。
解题思路
样例说明:删除权值为\(1\)和\(3\)的边,使得\(1.2.4\)三点不连通,答案为\(1 + 3 = 4\)。
使删除的边总权值最小可以转化为使添加的边总权值最大。
借鉴克鲁斯卡尔算法的基本思想:贪心地选取当前未被选过的权值最大的边,将其建入图内,直至所有的非指定点都被并入图内。
统计出加入的边的权值,答案即为总边权 - 统计出的边权。
注意事项
1.按边权从大到小排序。
2.数据范围大,用 \(long long\) 存变量。
#include <bits/stdc++.h>
#define re register
#define il inline
#define ll long long
#define MAXN 100005
#define MAXM 100005
#define rep(i,a,b) for(re int i = a;i <= b;++ i)
#define Rep(i,a,b) for(re int i = a;i < b;++ i)
#define drep(i,a,b) for(re int i = a;i >= b;-- i)
#define fin(a) freopen(#a".in","r",stdin)
#define fout(a) freopen(#a".out","w",stdout)
using namespace std;
struct edge{
int u,v,w;
}e[MAXM];
int n,k;
int fa[MAXN];
bool p[MAXN];
ll ans = 0;
il bool cmp(edge a,edge b){
return a.w > b.w;
}
il int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
il void kruskal(){
Rep(i,1,n){
int u = e[i].u,v = e[i].v,w = e[i].w;
int fu = find(u),fv = find(v);
if(p[fu] && p[fv])
continue;
fa[fu] = fv;
ans -= w;
if(p[fu])
p[fv] = 1;
else
if(p[fv])
p[fu] = 1;
}
}
int main(){
#ifndef ONLINE_JUDGE
fin(2700);
fout(2700);
#endif
scanf("%d%d",&n,&k);
rep(i,1,n)
fa[i] = i;
rep(i,1,k){
int point;
scanf("%d",&point);
p[point] = 1;
}
Rep(i,1,n){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
ans += e[i].w;
}
sort(e + 1,e + n + 1,cmp);
kruskal();
printf("%lld",ans);
return 0;
}
标签:洛谷,fu,fv,int,题解,fa,P2700,find,define 来源: https://www.cnblogs.com/StudyingVeyron-MUST/p/16675897.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。