Prime算法 与 Kruskal算法求最小生成树模板
算法原理参考链接 ==> UESTC算法讲堂——最小生成树
关于两种算法的复杂度分析 ==> http://blog.csdn.net/haskei/article/details/53132681
故稀疏图用 Kruskal、稠密图用 Prime、空间足够情况下都用 Prime + Heap 优化
下面的模板都是解决这一道题的模板
Prime模板
邻接矩阵版
#include<bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 1e2 + 10; int G[maxn][maxn], Dis[maxn], N; bool vis[maxn]; int Prime(int st) { int Cost = 0; for(int i=1; i<=N; i++) vis[i] = false, Dis[i] = G[st][i]; vis[st] = true; for(int i=1; i<N; i++){ int v, Min = INF; for(int j=1; j<=N; j++){ if(!vis[j] && Dis[j]<Min){ Min = Dis[j]; v = j; } } Cost += Dis[v]; vis[v] = 1; for(int j=1; j<=N; j++){ if(!vis[j] && Dis[j] > G[v][j]){ Dis[j] = G[v][j]; } } } return Cost; } int main(void) { while(~scanf("%d", &N)){ for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) scanf("%d", &G[i][j]); printf("%d\n", Prime(1)); } return 0; }
邻接表 + 堆优化
#include<bits/stdc++.h> using namespace std; const int maxn = 1e2 + 10; struct EDGE{ int v, nxt, w; }; struct NODE{ int v, cost; NODE(int vv, int cc):v(vv), cost(cc){}; bool operator < (const NODE &rhs)const{ return this->cost > rhs.cost; }; }; EDGE Edge[maxn*maxn]; bool vis[maxn]; int Head[maxn]; int N, cnt; inline void init() { for(int i=0; i<=N; i++) Head[i]=-1,vis[i]=false; cnt = 0; } inline void AddEdge(int from, int to, int weight) { Edge[cnt].v = to; Edge[cnt].w = weight; Edge[cnt].nxt = Head[from]; Head[from] = cnt++; } int Prime(int st) { int Cost = 0; NODE tp(st, 0); priority_queue<NODE> que; que.push(tp); int EdgeCnt = 0; while(!que.empty() && EdgeCnt<cnt){ tp = que.top(); que.pop(); if(vis[tp.v]) continue; else vis[tp.v] = true; Cost += tp.cost; EdgeCnt++; for(int j=Head[tp.v]; j!=-1; j=Edge[j].nxt){ if(!vis[Edge[j].v]) que.push(NODE(Edge[j].v, Edge[j].w)); } } return Cost; } int main(void) { while(~scanf("%d", &N)){ init(); int Val; for(int i=1; i<=N; i++){ for(int j=1; j<=N; j++){ scanf("%d", &Val); if(Val){ AddEdge(i, j, Val); } } } printf("%d\n", Prime(1)); } return 0; }
邻接表 + 配对堆优化
#include<bits/stdc++.h> #include<ext/pb_ds/priority_queue.hpp> using namespace __gnu_pbds; using namespace std; const int maxn = 1e2 + 10; struct EDGE{ int v, nxt, w; }; typedef pair<int, int> pii; EDGE Edge[maxn*maxn]; bool vis[maxn]; int Head[maxn]; int N, cnt; inline void init() { for(int i=0; i<=N; i++) Head[i]=-1,vis[i]=false; cnt = 0; } inline void AddEdge(int from, int to, int weight) { Edge[cnt].v = to; Edge[cnt].w = weight; Edge[cnt].nxt = Head[from]; Head[from] = cnt++; } int Prime(int st) { int Cost = 0; __gnu_pbds::priority_queue< pii, greater<pii>, pairing_heap_tag > que; que.push(make_pair(0, st)); int EdgeCnt = 0; while(!que.empty() && EdgeCnt<cnt){ pii tp = que.top(); que.pop(); int v = tp.second; if(vis[v]) continue; else vis[v] = true; Cost += tp.first; EdgeCnt++; for(int j=Head[v]; j!=-1; j=Edge[j].nxt){ if(!vis[Edge[j].v]) que.push(make_pair(Edge[j].w, Edge[j].v)); } } return Cost; } int main(void) { while(~scanf("%d", &N)){ init(); int Val; for(int i=1; i<=N; i++){ for(int j=1; j<=N; j++){ scanf("%d", &Val); if(Val){ AddEdge(i, j, Val); } } } printf("%d\n", Prime(1)); } return 0; }
Kruskal模板
#include<bits/stdc++.h> using namespace std; const int maxn = 210;//最大点数 int c[maxn], N;//并查集使用 int cnt; struct EDGE{ int from, to, w; bool operator < (const EDGE &rhs) const{ return this->w < rhs.w; }; }Edge[maxn*maxn];//储存边的信息,包括起点/终点/权值 inline void init() { for(int i=0; i<=N; i++) c[i] = i; cnt = 0; } inline void AddEdge(int from, int to, int weight) { Edge[cnt].from = from; Edge[cnt].to = to; Edge[cnt].w = weight; cnt++; } int Findset(int x) { int root = x; while(c[root] != root) root = c[root]; int idx; while(c[x] != root){ /// 路径压缩 idx = c[x]; c[x] = root; x = idx; } return root; } int Kruskal()//传入点数,返回最小生成树的权值,如果不连通返回-1 { sort(Edge,Edge+cnt); int EdgeCnt=0;//计算加入的边数 int Cost=0; for(int i=0;i<cnt;i++){ int R1 = Findset(Edge[i].from); int R2 = Findset(Edge[i].to); if(R1 != R2){ Cost += Edge[i].w; c[R1]=R2; EdgeCnt++; } if(EdgeCnt==N-1) break; } if(EdgeCnt<N-1) return -1;//不连通 else return Cost; } int main() { while(~scanf("%d", &N)){ init(); int Val; for(int i=1; i<=N; i++){ for(int j=1; j<=N; j++){ scanf("%d", &Val); if(Val){ AddEdge(i, j, Val); } } } printf("%d\n", Kruskal()); } return 0; }