刷题刷到自闭,写个博客放松一下

题意:n个人,m对朋友,每寻找一个人传播消息需要花费相应的价钱,朋友之间传播消息不需要花钱,问最小的花费

把是朋友的归到一起,求朋友中花钱最少的,将所有最少的加起来。

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<string.h>
 4 #define ll long long
 5 using namespace std;
 6 
 7 ll a[1000100];
 8 
 9 struct lll
10 {
11     ll par,b,c;
12 }p[100100];
13 
14 int cmp(lll x,lll y)
15 {
16     if(x.par==y.par) return x.b<y.b;
17     return x.par<y.par;
18 }
19 
20 ll find(ll x)
21 {
22     if(x!=p[x].par) p[x].par=find(p[x].par);
23     return p[x].par;
24 }
25 
26 void unionn(ll x,ll y)
27 {
28     ll fa=find(x);
29     ll fb=find(y);
30     if(fb==fa) return ;
31     if(p[fa].c<p[fb].c){
32         p[fa].par=fb;
33     }
34     else p[fb].par=fa;
35     if(p[fa].c==p[fb].c) p[fa].c++;
36 }
37 
38 int main()
39 {
40     ll n,m;
41     while(scanf("%lld%lld",&n,&m)!=EOF){
42         memset(a,0,sizeof a);
43         memset(p,0,sizeof p);
44         for(ll i=1;i<=n;i++){
45             scanf("%lld",&a[i]);
46             p[i].par=i;
47             p[i].b=a[i];
48             p[i].c=0;
49         }
50         ll x,y;
51         for(ll i=0;i<m;i++){
52             scanf("%lld%lld",&x,&y);
53             unionn(x,y);
54         }
55         ll sum=0;
56         for(int i=1;i<=n;i++)
57             while(p[i].par!=i&&p[p[i].par].par!=p[i].par)       //是同一类但是头不是老大 把头变为老大;
58                 p[i].par=p[p[i].par].par;
59         sort(p+1,p+n+1,cmp);                //把结构体按类排序,主要是同一类的花费少的在前
60         sum=p[1].b;
61         for(int i=2;i<=n;i++){
62             if(p[i].par!=p[i-1].par) sum+=p[i].b;       //是同一类的加上花费最少的第一个 不是同一类就继续循环
63         }
64         printf("%lld\n",sum);
65     }
66     return 0;
67 }