口袋的天空
我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 }
一切无法杀死我的,都将使我变得更加强大。