口袋的天空

我tm又把n和m打反了。

原题链接:https://www.luogu.org/problemnew/show/1195#sub

为什么我找到的并查集的题都基本上可以用kruskal做啊。。并查集明明可以干很多事情的好不好。。

既然要把n个点连成k个“块”,那自然想到连边要连n-k条。

我们对所有边信息按照边权升序排序,然后枚举所有边,如果有一条边连接的两个点不在同一集合就合并并维护相关信息。

(这tm还是kruskal,做了多少了都)

如果发现已经连好了n-k条边输出权值和就好。

最后就是无解的情况了。

参考代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define maxn 1000005
 6 using namespace std;
 7 inline int read(){
 8     int num = 0;
 9     char c;
10     bool flag = false;
11     while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
12     if (c == '-')
13         flag = true;
14     else
15         num = c - '0';
16     while (isdigit(c = getchar()))
17         num = num * 10 + c - '0';
18     return (flag ? -1 : 1) * num;
19 }
20 
21 struct Edge{
22     int from,to,dis;
23     bool operator<(const Edge &rhs)const{
24         return dis < rhs.dis;
25     }
26 };
27 Edge edge[maxn];
28 int father[maxn];
29 int n,m,k,ans;
30 int totedge = 0;
31 void init(){
32     for (register int i=1;i<=n;i++)
33         father[i] = i;
34 }
35 int find(int x){
36     if (father[x] == x)
37         return father[x];
38     return x = find(father[x]);
39 }
40 int main(){
41     n = read();m = read();k = read();
42     init();
43     for (register int i=1;i<=m;i++){
44         edge[i].from = read();
45         edge[i].to = read();
46         edge[i].dis = read();
47     }
48     sort(edge+1,edge+m+1);
49     init();
50     for (int i=1;i<=m;i++){
51         if (find(edge[i].from) != find(edge[i].to)){
52             father[find(edge[i].from)] = find(edge[i].to);
53             totedge++;
54             ans += edge[i].dis;
55         }
56         if (totedge == n-k){
57             printf("%d\n",ans);
58             return 0;
59         }
60     }
61     printf("No Answer");
62     return 0;
63 }

 

posted @ 2017-10-23 23:58  ShawnZhou_Aether  阅读(193)  评论(0编辑  收藏  举报