1 prim 算法 O(n2) 贪心
/* 最小生成树Prim 算法: 贪心思想,随机选择一个点当做最小生成树的初始节点,然后把图的顶点分成A集合(含初始节点), B集合(剩余节点)每次选择A集合中的点到B集合中点的最短距离的边,然后用加入的点去松弛A集合点到B集合点的距离信息。不断迭代, 最终得到最小生成树。 */ struct Edge{ int start_, end_; float weight_; }; void prim(vector<vector<int>> &map, Edge *&mist){ int n = map.size(); if(n < 1) return ; mist = new Edge[n]; if(mist == NULL) return ; for(int i - 0; i < n; ++i){ mist[i].start_ = 0; mist[i].end_ = i; mist[i].weight_ = map[0][i]; } for( int i = 1; i< n; ++i){ int minWeight = mist[i].weight_; int minIndex = i; for(int j = i+1 ; j< n; ++j){ if(mist[j].weight_ < minWeight){ minWeight = mist[j].weight_; minIndex = j; } } if(minIndex != i){ Edge tp = mist[i]; mist[i] = mist[minIndex]; mist[minIndex] = tp; } int x = mist[i].end_,y; for(int j = i+1; j<n; ++j){ y = mist[j].end_; if(map[x][y] < mist[j].weight_){ mist[j].start_ = x; mist[j].weight = map[x][y]; } } } }
2 最短路径dijkstra 算法 贪心思想
struct path{ int pre; int length; path(){ pre = -1; length = INT_MAX; } }; void dijkstra(vector<vector<int>> &graph, path *&dist, int v){ int n = graph.size(); if(v < 0 || v >= n) return ; if(n == 0) return; dist = new path[n]; if(dist == NULL) return ; for(int i = 1; i< n; ++i){ if(graph[v][i] != INT_MAX){ dist[i].pre = v; dist[i].length = graph[v][i]; } } graph[v][v] = 1; for(int i = 1; i < n ; ++i){ int min = -1, minLength = INT_MAX; for(int j = 0; j < n; ++j){ if(graph[j][j] != 1 && dist[j].length < minLength){ minLength = dist[j].length; min = j; } } if(min == -1) return ; graph[min][min] = 1; for(int j = 0; j< n;++j){ if(graph[j][j] == 1) continue; int tp = dist[min].length + graph[min][j]; if(tp < dist[j].length){ dist[j].length = tp; dist[j].pre = min; } } } }
3 floyd 非贪心 O(n3)
void floyd(vector<vector<int>> &graph, vector<vector<int>> &path){ int n = graph.size(); if(n == 0) return ; graph.resize(n, vector<int>(n)); vector<vector<int>> p(n,vector<int>(n,0)); for(int i = 0; i< n; ++i) for(int j = 0; j< n; ++j) { if(graph[i][j] != INT_MAX) path[i][j] = j; else path[i][j] = -1; p[i][j] = graph[i][j] ; } for(int k = 0; k< n; ++k) for(int i = 0; i< n; ++i) for(int j = 0; j< n; ++j) { if(p[i][k] == INT_MAX || p[k][j] == INT_MAX) continue; int tp = p[i][k] + p[k][j]; if(tp < p[i][j]){ p[i][j] = tp; path[i][j] = path[i][k]; } } }