P1195 口袋的天空

链接:P1195

------------------------------

这道题第一眼肯定能想到最小生成树,不过最小生成树最后就成了一个连通块。

哎,最后?我们想一下卡鲁斯卡尔算法,是一次加上一条边,而且这边的两端不再一个联通块中。

也就是说,我们的每一次操作,就相当于消除了一个连通块。

这样,我们在最后留下k个联通块不就可以了?

-----------------------------

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 int p;
 6 struct b{
 7     int f;
 8     int to;
 9     int v;
10 }bian[10500];
11 int n,m,k;
12 int fa[105000];
13 int find(int x){
14     if(x==fa[x])
15     return x;
16     else
17     return fa[x]=find(fa[x]);
18 }
19 int on(int x,int y){
20     int x1=find(x);
21     int y1=find(y);
22     if(x1!=y1)
23     fa[x1]=y1;
24 }
25 bool cmp(b a,b c){
26     return a.v<c.v;
27 }
28 int x,y,l;
29 int ans;
30 int main(){
31     cin>>n>>m>>k;
32     for(int i=1;i<=m;++i){
33         scanf("%d%d%d",&x,&y,&l);
34         p++;
35         bian[p].f=x;
36         bian[p].to=y;
37         bian[p].v=l;    
38     }
39     for(int i=1;i<=n;++i)
40     fa[i]=i;
41     if(m!=1)
42     sort(bian+1,bian+1+m,cmp);
43         int k1=n-k;
44         int flag=1;
45         while(k1){
46             int u=bian[flag].f;
47             int v=bian[flag].to;
48             if(find(u)!=find(v)){
49                 k1--;
50                 ans+=bian[flag].v;
51                 on(u,v);
52             }
53             flag++;
54         }
55     cout<<ans;
56     return 0;
57 } 
Ac

 

posted @ 2019-07-28 10:49  Simex  阅读(165)  评论(0编辑  收藏  举报