题目: http://acm.hdu.edu.cn/showproblem.php?pid=1102
本题的给输入是矩阵的存储,但最后又给出已经修好的路,所以我先用矩阵存储输入,再将其中的边提出来,用
struct Edge{
int u,v,w;
};
存储,因为下面用kruskal就方便了。(这个题目首先你要知道用kruskal)
对于已经修好的路的顶点,用并查集合并其顶点集合。
接下来扫描顶点1到N,找出其父亲结点,我用set<int> rgSet存储,很方便找出1到N化分成的集合数目。
然后就是再加入minnum条边就行了。
#include <iostream> #include <cstdio> #include <functional> #include <set> #include <algorithm> using namespace std; #define MAXV 111 #define INF 32767 struct Tree { int parent; int rank; } t[MAXV]; struct Edge { int u, v, w; bool operator <(const Edge &elem) const { return w < elem.w; } } edge[MAXV*MAXV]; struct Graph { int matrix[MAXV][MAXV]; int n; }; void Make_Set(int n) { int i; for (i = 0; i <= n; ++i) { t[i].parent = i; t[i].rank = 0; } } int Find_Set(int x) { int i, j, r; r = x; while (t[r].parent != r) { r = t[r].parent; } i = x; while (t[i].parent != r) { j = t[i].parent; t[i].parent = r; i = j; } return r; } int Union_Set(int x, int y) { if (t[x].rank > t[y].rank) { t[y].parent = x; return x; } else { t[x].parent = y; if (t[x].rank == t[y].rank) t[y].rank++; return y; } } int Kruskal(int N,int E) { int i, j, a, b, Q; int s1, s2; int ret = 0; sort(edge, edge + E); // 注意这里是对边sort Make_Set(N); // 这里是对顶点集合1到N初始化, 这两行的别晕了,run time error 好多次才找出来。。汗。。 // ---------------- scanf("%d", &Q); for (i = 0; i < Q; ++i) { scanf("%d%d", &a, &b); a = Find_Set(a); b = Find_Set(b); if (a != b) Union_Set(a, b); } set<int> rgSet; for(i=1;i<=N;++i) rgSet.insert(Find_Set(i)); i=rgSet.size(); i-=1; j = 0; while (i > 0) { s1 = Find_Set(edge[j].u); s2 = Find_Set(edge[j].v); if (s1 != s2) { Union_Set(s1, s2); ret += edge[j].w; --i; } ++j; } rgSet.clear(); return ret; } int main() { // freopen("input.txt", "r", stdin); int N,E; int i, j; Graph g; while (scanf("%d", &N) != EOF) { E=0; for (i = 0; i < N; ++i) for (j = 0; j < N; ++j) scanf("%d", &g.matrix[i][j]); for (i = 0; i < N; ++i) for (j = i + 1; j < N; ++j) { edge[E].u = i+1; edge[E].v = j+1; edge[E].w = g.matrix[i][j]; E+=1; } printf("%d\n", Kruskal(N,E)); } return 0; }