【2018百度之星资格赛】F 三原色图 - 最小生成树

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6349

 

Knowledge Point: 最小生成树算法Prim&Kruskal

 

Summarize:

  本题采用构造两颗带权最小生成树的方法求解;

  求解最小生成树的方法有prim和kruskal两种方法,但是网上题解皆采用的后者;

  我用prim写了之后发现AC不了,主要是prim采用的邻接矩阵的方法存储边对这道题不适用,题目没有说过没有重复的边,而邻接矩阵会覆盖掉上一条颜色相同的边;

  此外需注意:

    1. 点数为1时特判;

    2. 当边数小于点数减一的时候可以直接判断无解;

    3. 当两棵树最小权值相同或都有解时,需分别记录两个最小值,并分别与当时剩下的边相加,每次都需比较之后再输出两者之间的最小值。

 

附kruskal代码,先按边从小到大排序后再依次求解:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 #define INF 1e9
 7 const int N = 1e5+5;
 8 const int M = 5e5+5;
 9 int n,m;
10 struct Edge {
11     int from, to, value;
12     bool operator<(const Edge &a) {
13         return value<a.value;
14     }
15 }edge[M];
16 int vis[N], f[N];
17 
18 int find(int x)
19 {
20     if(x != f[x])
21         f[x] = find(f[x]);
22     return f[x];
23 }
24 
25 void init()
26 {
27     for(int i=0; i<n; i++)
28         vis[i]=0, f[i] = i;
29     sort(edge, edge+m);
30 }
31 
32 void kruskal()
33 {
34     int cost=0;
35     for(int i=0; i<m; i++) {
36         int x = find(edge[i].from);
37         int y = find(edge[i].to);
38         if(x != y) {
39             f[x] = y;
40             cost += edge[i].value;
41             vis[edge[i].from] = vis[edge[i].to] = 1;
42         }
43     }
44     cout<<cost<<endl;
45 }
46 
47 int main()
48 {
49     cin>>n>>m;
50     for(int i=0; i<m; i++)
51         cin>>edge[i].from>>edge[i].to>>edge[i].value;
52     
53     init();
54     kruskal();
55     
56     return 0;
57 }

 

posted @ 2018-08-07 21:42  liubilan  阅读(229)  评论(0编辑  收藏  举报