hdu 1863
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1863
题意:中文。。。
mark:继续看题解。。神奇的最小生成树+并查集,算法名字叫Kruskal。听起来很高深的样子,但是算法理解起来不难,就是遇到这类型的题目,首先存放的是每条边的起点,终 点和权值,然后将所有边按权值的升序排序,然后从最小权值开始查找,用到并查集的方法,只须修改一下并查集里面merge函数,当发现当前边的起点和终点已经可以直接 或间接连在一起的时候,就不用管它,否则就将这两个点通过当前边连接起来,最后判断一下是否所有点都已经连接起来。
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <iostream> #include <algorithm> #include <map> #include <set> #include <stack> #include <queue> #include <vector> using namespace std; typedef long long LL; typedef struct { int u,v,w; }ss; ss s[110]; int tt[110]; int n,m; int cmp(const void *a, const void *b) { return (*(ss *)a).w - (*(ss *)b).w; } int find(int a) { while(a != tt[a]) a = tt[a]; return a; } int merge(int a, int b) { a = find(a); b = find(b); if(a != b) { tt[a] = b; return 1; } return 0; } int main(int argc, char **argv) { int i,j,k; while(cin >> n >> m) { if(!n) break; for(i = 0; i < n; i++) cin >> s[i].u >> s[i].v >> s[i].w; qsort(s, n, sizeof(ss), cmp); for(i = 1; i <= m; i++) tt[i] = i; int sum = 0; for(i = 0; i < n; i++) if(merge(s[i].u, s[i].v)) sum += s[i].w; int cnt = 0; for(i = 1; i <= m; i++) if(tt[i] == i) cnt++; if(cnt == 1) cout << sum << endl; else cout << '?' << endl; } return 0; }