【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 }