1、mst 没有堆优化的prim算法
原题链接: http://hihocoder.com/problemset/problem/1097
1 //原题链接: http://hihocoder.com/problemset/problem/1097 2 3 #include <iostream> 4 #include <cstdio> 5 #include <set> 6 #include <cstring> 7 #include <climits> 8 using namespace std; 9 10 int gra[1010][1010]; 11 int vis[1010]; 12 int min_dis[1010]; //图上的每个节点到mst的距离 13 14 int main() { 15 memset(gra, 0x7f, sizeof(gra)); 16 memset(vis, 0, sizeof(vis)); 17 memset(min_dis, 0x7f, sizeof(min_dis)); 18 int n; 19 scanf("%d", &n); 20 for (int i = 0; i < n; ++i) { 21 for (int j = 0; j < n; ++j) { 22 scanf("%d", &gra[i][j]); 23 } 24 } 25 //初始化 26 vis[0] = 1; 27 int left = n - 1; 28 min_dis[0] = 0; //第0个节点就是树开始计算的第一个结点 29 for (int i = 1; i < n; ++i) { 30 min_dis[i] = gra[0][i]; 31 } 32 33 int min_cost = 0; 34 35 while (left) { 36 int vertex = 1, minn_dis = INT_MAX; 37 //从没有访问过的所有节点中找出距离树的距离最小的一个. 38 for (int i = 0; i < n; ++i) { 39 if (!vis[i] && min_dis[i] < minn_dis) { 40 vertex = i, minn_dis = min_dis[i]; 41 } 42 } 43 vis[vertex] = true; 44 min_cost += minn_dis; 45 left--; 46 //printf("%d : vertex: %d; minn_dis[%d] ", n - left - 1, vertex, minn_dis); 47 48 //把找到的新的点加到mst中,然后更新每个没有访问过的结点到mst的距离 49 for (int i = 0; i < n; ++i) { 50 if (!vis[i] && min_dis[i] > gra[vertex][i]) { 51 min_dis[i] = gra[vertex][i]; 52 } 53 } 54 } 55 printf("%d ", min_cost); 56 return 0; 57 }
2、并查集优化的kruskal算法
原题链接:https://hihocoder.com/problemset/problem/1098
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 7 using namespace std; 8 9 int u[1000100], v[1000100], w[1000100], r[1000100]; 10 int fa[100020]; 11 12 bool cmp (const int x, const int y) { 13 return w[x] < w[y]; 14 } 15 16 void initSet(const int n) { 17 for (int i = 0; i < n; ++i) { 18 fa[i] = i; 19 } 20 } 21 22 int find(int x) { 23 return x == fa[x] ? x : fa[x] = find(fa[x]); 24 } 25 26 int main() { 27 int n, m; 28 scanf("%d %d", &n, &m); 29 30 initSet(n); //初始化并查集 31 for (int i = 0; i < m; ++i) { 32 scanf("%d %d %d", &u[i], &v[i], &w[i]); 33 r[i] = i; //初始化边的序号 34 } 35 sort(r, r + m, cmp); //把边按照边的权重间接排序 36 37 /* 38 //打印sort之后的值 39 for(int i = 0; i < m; ++i) { 40 int idx = r[i]; 41 printf("%d %d %d ", u[idx], v[idx], w[idx]); 42 } 43 */ 44 45 int ans = 0; 46 int cnt = 0; 47 for(int i = 0; i < m; ++i) { 48 int e = r[i]; 49 int x = find(u[e]), y = find(v[e]); //找出当前两个端点所在的集合编号 50 if (x != y) { //不在同一个集合则合并 51 ans += w[e]; 52 fa[x] = y; 53 cnt++; 54 if (cnt == n-1) { 55 break; 56 } 57 } 58 } 59 printf("%d ", ans); 60 return 0; 61 }
3、求最短路的算法
(1)floyed (O(N^3))
(2)Dijkstra(O(nlogn))堆优化之后的算法
例题:https://www.luogu.org/problemnew/show/P3366
1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 int graph[1005][1005]; 8 int n, m; 9 int res = 1; 10 struct HeapNode { 11 int u, d; 12 HeapNode(int node, int weight): u(node), d(weight) {} 13 bool operator<(const HeapNode& rhs) const { 14 return d > rhs.d; 15 } 16 }; 17 void dijkstra(int src) { 18 vector<int> dis(n, INT_MAX); 19 dis[0] = 0; 20 priority_queue<HeapNode> que; 21 que.push(HeapNode(src, 0)); 22 while (!que.empty()) { 23 HeapNode cur = que.top(); que.pop(); 24 int u = cur.u, d = cur.d; 25 if (dis[u] != d) {continue;} 26 for (int v = 0; v < n; ++v) { 27 if (graph[u][v] == -1) {continue;} 28 if (dis[u] + graph[u][v] < dis[v]) { 29 dis[v] = dis[u] + graph[u][v]; 30 que.push(HeapNode(v, dis[v])); 31 } 32 } 33 } 34 for (auto d : dis) { 35 printf("%d ", d); 36 } 37 printf(" "); 38 39 } 40 int main(int argc, char *argv[]) { 41 cin >> n >> m; 42 memset(graph, -1, sizeof(graph)); 43 for (int k = 0; k < m; ++k) { 44 int u, v, w; 45 cin >> u >> v >> w; 46 graph[u-1][v-1] = w; 47 } 48 dijkstra(0); 49 }