我不知道为什么prim算法跟最短路的dijkstra算法很像,很像很像。。。
prim算法的思想也是维护两个集合,一个是源点集合,一个非源点集合,每次把非源点集合中的离源点集合最近的点加入源点集合(注意这里的“距离”跟dijkstra算法中的距离不同,这里的距离是指到源点集合中任意一点的距离,而dijkstra中距离是指到源点的距离),知道没有可加入的点,最小生成树就形成了。
复杂度O(|V|^2)
vector<int>g[N], e[N];
int dis[N];
bool vis[N];
void add(int u, int v, int c){
g[u].push_back(v);
e[u].push_back(c);
}
int prim(int n){
memset(vis, false, sizeof vis);
memset(dis, 0x3f, sizeof dis);
dis[1] = 0;
vis[1] = true;
int u = 1, nn = n, ret = 0;
while (nn--){
for (int i = 0; i < g[u].size(); i++){
int v = g[u][i], c = e[u][i];
dis[v] = min(dis[v], c);
}
u = -1;
for (int i = 1; i <= n; i++){
if (vis[i] == false && (u == -1 || dis[i] < dis[u]))
u = i;
}
if (u == -1)break;
ret += dis[u];
vis[u] = true;
}
return ret;
}
我只是练习一下数组存储邻接表
int first[N], cost[N*N], nxt[N*N], to[N*N], e;
int dis[N];
bool vis[N];
void add(int u, int v, int c){
cost[e] = c;
nxt[e] = first[u];
to[e] = v;
first[u] = e++;
}
int prim(int n){
memset(vis, false, sizeof vis);
memset(dis, 0x3f, sizeof dis);
dis[1] = 0;
vis[1] = true;
int u = 1, nn = n, ret = 0;
while (nn--){
for (int i = first[u]; i != -1; i = nxt[i]){
int v = to[i], c = cost[i];
dis[v] = min(dis[v], c);
}
u = -1;
for (int i = 1; i <= n; i++){
if (vis[i] == false && (u == -1 || dis[i] < dis[u]))
u = i;
}
if (u == -1)break;
ret += dis[u];
vis[u] = true;
}
return ret;
}