很简单的最小生成树类型,直接求连一起的最小路程。
Prim算法和DIJ很类似啊,就变了一步。。。
KRU让我纠结了好长时间,不过还好明白了,PRE数组中存的是与i同一集合的下标。。。
//2015.9.16 复习Prim,被以前的代码丑哭了,更新一下
Prim
#include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <memory> #include <string.h> #include <string> #include <algorithm> using namespace std; class Node { public : Node *next; int to; int val; Node(int to, int val, Node* next) : to(to), val(val), next(next) {} }; void add(vector<Node*> &road, int from, int to, int val) { Node *t = new Node(to, val, road[from]); road[from] = t; } void input(int n, vector<Node*> &road) { getchar(); char from, to; int num, len; for (int i = 1; i < n; i++) { scanf("%c %d", &from, &num); int a = from - 'A'; while (num--) { scanf(" %c %d", &to, &len); int b = to - 'A'; add(road, a, b, len); add(road, b, a, len); } getchar(); } } void prim(int n, vector<Node*> &road) { vector<bool> visit(n, false); vector<int> dist(n, INT_MAX); int now = 0, sum = 0; dist[0] = 0; visit[0] = true; for (int i = 1; i < n; i++) { for (auto head = road[now]; head != NULL; head = head->next) { int to = head->to, len = head->val; if (!visit[to] && dist[to] > len) { dist[to] = len; } } int min_len = INT_MAX; for (int k = 0; k < n; k++) { if (!visit[k] && dist[k] < min_len) { min_len = dist[now = k]; } } sum += min_len; visit[now] = true; } printf("%d\n", sum); } int main(void) { int n; while (scanf("%d",&n) != EOF && n) { vector<Node*> road(n, NULL); input(n, road); prim(n, road); } return 0; }
Kruskal
//2015.9.16 更新
#include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <memory> #include <string.h> #include <string> #include <algorithm> using namespace std; class Edge { public : int u, v, len; Edge(int u, int v, int len) : u(u), v(v), len(len) {} bool operator<(const Edge &a) const { return this->len < a.len; } }; void input(int n, vector<Edge> &edge) { getchar(); char from, to; int num, len; for (int i = 1; i < n; i++) { scanf("%c %d", &from, &num); int a = from - 'A'; while (num--) { scanf(" %c %d", &to, &len); int b = to - 'A'; edge.push_back(Edge(a, b, len)); } getchar(); } } int findPre(int x, vector<int> &pre) { while (x != pre[x]) x = pre[x]; return x; } int kruskal(int n, vector<Edge> &edge) { sort(edge.begin(), edge.end()); vector<int> pre(n, 0); int sum = 0; for (int i = 0; i < n; i++) { pre[i] = i; } for (auto &e : edge) { int a = findPre(e.u, pre); int b = findPre(e.v, pre); if (a != b) { pre[b] = a; sum += e.len; } } return sum; } int main(void) { int n; while (scanf("%d",&n) != EOF && n) { vector<Edge> edge; input(n, edge); cout << kruskal(n, edge) << endl; } return 0; }