F. Make It Connected(krustra+)
题目大意:首先给你n个点,然后给你每个点的权值,再给你m条边,这些边可以选也可以不选,然后问你要使这个加边构成的图联通的最小花费。
具体思路:我们可以先找出权值最小的点,然后别的点都向向这个点连一条边,这是当前使得图联通的最小构图的方法,然后再看一下题目给定的点加上,注意题目给定的权值不一定是最小的。(如果是用spfa算法的话,就需要建立双向边,然后用krustra的话,没有建立双向边的必要,建立起来就可以了)
AC代码:
1 #include <iostream> 2 #include<stdio.h> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 # define ll long long 8 # define LL_inf 1ll<<60 9 const int maxn =4e5+10; 10 struct node 11 { 12 int fr; 13 int to; 14 ll cost; 15 } q[maxn]; 16 ll a[maxn]; 17 int father[maxn],num; 18 int Find(int t) 19 { 20 return t==father[t]?t:father[t]=Find(father[t]); 21 } 22 bool cmp(node t1,node t2) 23 { 24 return t1.cost<t2.cost; 25 } 26 ll krustra() 27 { 28 ll sum=0; 29 for(int i=1; i<=num; i++) 30 { 31 int t1=Find(q[i].fr); 32 int t2=Find(q[i].to); 33 if(t1!=t2) 34 { 35 father[t1]=t2; 36 sum+=q[i].cost; 37 } 38 } 39 return sum; 40 } 41 int main() 42 { 43 int n,m; 44 scanf("%d %d",&n,&m); 45 ll minn=LL_inf; 46 int id=0; 47 for(int i=1; i<=n; i++) 48 { 49 father[i]=i; 50 scanf("%lld",&a[i]); 51 if(a[i]<minn) 52 { 53 minn=a[i]; 54 id=i; 55 } 56 } 57 int st,ed; 58 ll co; 59 for(int i=1; i<=m; i++) 60 { 61 scanf("%d %d %lld",&st,&ed,&co); 62 co=min(a[st]+a[ed],co); 63 q[++num].fr=st; 64 q[num].to=ed; 65 q[num].cost=co; 66 } 67 for(int i=1; i<=n; i++) 68 { 69 if(i==id) 70 continue; 71 q[++num].fr=i; 72 q[num].to=id; 73 q[num].cost=a[i]+a[id]; 74 } 75 sort(q+1,q+num+1,cmp); 76 ll ans=krustra(); 77 printf("%lld\n",ans); 78 return 0; 79 } 80