标签:
方法一:该种方法使用于点少,路经多的情况 #include<stdio.h> #include<string.h> #include<queue> # define N 110 using namespace std; int G[N][N]; struct node { int x, y, len; friend bool operator < (node a, node b) { return a.len > b.len; } }; //优先队列,从小到大排序 int Prim(int n) { int i, k = 1, ans = 0, v[N] = {0}; v[1] = 1; //标志数组,用于判断该点是否已经找到 node s, e; priority_queue<node>Q; for (i = 2; i <= n; i++) { s.x = 1, s.y = i; s.len = G[1][i]; Q.push(s); } //先将第一个找到,入队列 while (k < n) { s = Q.top(); Q.pop(); if (v[s.y] == 0) { v[s.y] = 1; //将1对应的下一条最短路径找到,置为1 k++; //记录找到几个点 ans += s.len; //此时需要加上该最短路径 for (i = 1; i <= n; i++) { e.x = s.y, e.y = i; e.len = G[s.y][i]; if (e.len != -1 && v[i] == 0) Q.push(e); //要是该点未被找到且存在路经,入队列 } } } return ans; } int main () { int i, n, ans, a, b, c; while (scanf("%d", &n), n) { memset(G, -1, sizeof(G)); //以防有些路经不存在 for (i = 0; i < n*(n-1)/2; i++) { scanf("%d %d %d", &a, &b, &c); G[a][b] = G[b][a] = c; //路经是互通的 } ans = Prim(n); printf("%d\n", ans); } return 0; }
方法二:该方法适用于点多路径少的情况 #include<stdio.h> #include<queue> # define N 110 using namespace std; struct node { int x, y, len; friend bool operator < (node a, node b) { return a.len > b.len; } }; //优先队列,也可以用快排来排序 int F[N]; int Find(int x) { if (x != F[x]) x = Find(F[x]); return x; } //查找x的根节点,运用了并查集,这里是为了判断两个点是否在一个集合中 int main () { int i, n, ans; while (scanf("%d", &n), n) { node s; priority_queue<node>Q; ans = 0; for (i = 0; i < n*(n-1)/2; i++) { scanf("%d %d %d", &s.x, &s.y, &s.len); Q.push(s); //输入的时候直接进队列 } for (i = 1; i <= n; i++) F[i] = i; //查找根节点的数组要初始化,一开始自己的根节点就是本身 while (!Q.empty()) //当队列非空时 { s = Q.top(); Q.pop(); s.x = Find(s.x); s.y = Find(s.y); if (s.x != s.y) { F[s.x] = s.y; ans += s.len; } //若两点不在一个集合,那就在这两点修路,使之在一个集合内 } printf("%d\n", ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/syhandll/p/4470158.html