概念:树的节点间都有权值,求连通所有节点所需要的最短节点
Krucal算法:(利用并查集)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;//点边输入
const int maxn = 1e6 + 10;
int pre[maxn];
int n,m;
struct node{
int u,w;
int value;
}a[maxn];
bool cmp(node a,node b){
return a.value < b.value;
}
int find(int x){
return pre[x] == x ? x : pre[x] = find(pre[x]);
}
void merge(int x,int y){
int fx = find(x);
int fy = find(y);
if(fx == fy) return ;
pre[fx] = fy;
}
int main(){
int x,y,ans;
while(scanf("%d%d",&n,&m)!=EOF){
memset(a,0,sizeof(a));
for(int i = 1;i<=n;i++) pre[i] = i;
for(int i = 1;i<=m;i++) scanf("%d%d%d",&a[i].u,&a[i].w,&a[i].value);
sort(a+1,a+m+1,cmp);
ans = 0;
for(int i = 1;i<=m;i++){
x = find(a[i].u);
y = find(a[i].w);
if(x != y){
ans += a[i].value;
pre[x] = y;
}
//else continue;
}
printf("%d\n",ans);
}
return 0;
}
prime算法
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1000 + 10;
const int INF = 0x3f3f3f3f;
int n;
int mincost[maxn];//从集合x出发的边到每个顶点的最小权值
int cost[maxn][maxn];
bool vis[maxn];
int prim(){
for(int i = 0;i<n;i++){
mincost[i] = INF;
vis[i] = false;
}//初始化
mincost[0] = 0;
int res = 0;
while(1){
int v = -1;
for(int i = 0;i < n;++i){
if(!vis[i] && (v == -1 || mincost[i] < mincost[v])) v = i;
}
if(v==-1) break;
vis[v] = true;
res += mincost[v];
for(int i = 0;i < n;i++){
mincost[i] = min(mincost[i],cost[v][i]);
}
}
return res;
}
int main(){
scanf("%d",&n);
int z;
for(int i = 0;i<n;i++)
for(int j = 0;j<n;j++)
if(i!=j) cost[i][j] = INF;
for(int i = 0;i<n;i++){
for(int j = 0;j<n;j++){
scanf("%d",&z);
if (cost[i][j] == INF || (cost[i][j]!=INF && cost[i][j] > z)){ //判断是否有重边,有就更新最小值
cost[i][j] = z;
cost[j][i] = z;
}
}
}
int ans = prim();
printf("%d\n",ans);
}
prime优化:
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1005;
int V,E;
struct node{
int to,w;
bool operator < (const node &b)const{
return w > b.w;
} //w越小的优先级越高,保证在优先队列里取出的第一个的w最小
};
vector<node> spot[MAXN];
bool vis[MAXN];
priority_queue<node > q;
int prim(){
while (!q.empty()) q.pop();
memset(vis,false,sizeof(vis));
int res = 0;
for (int i = 0; i < spot[V].size(); ++i){ //取一个起点
q.push(spot[V][i]);
}
vis[V] = true;
node temp;
for (int i = 0; i < V-1; ++i){
temp = q.top(); q.pop();
while (vis[temp.to]){
temp = q.top();
q.pop();
}
res += temp.w;
vis[temp.to] = true;
for (int j = 0; j < spot[temp.to].size(); ++j){//处理选择的点能到达的所有的点(且未被访问)
if (!vis[ spot[temp.to][j].to ]){
q.push(spot[temp.to][j]);
}
}
}
return res;
}
int main(){
while (scanf("%d%d",&V,&E)!=EOF){
int x,y,z;
for (int i = 0; i < E; ++i){
scanf("%d%d%d",&x,&y,&z);
node temp;
temp.to = y;temp.w = z;
spot[x].push_back(temp);
temp.to = x;
spot[y].push_back(temp);
}
int ans = prim();
printf("%d\n",ans);
}
return 0;
}