普利姆算法(prim)
朴素版 稠密图常用 O(n^2)
借助临界矩阵存储g[N][N]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| const int INF=0x3f3f3f3f; int prim(){ int res=0; memset(dist,0x3f,sizeof(dist));
for(int i=0;i<n;i++){ int t=-1; for(int j=1;j<=n;j++){ if(!st[j]&&(t==-1||dist[t]>dist[j]){ t=j; } } if(i&&dist[t]==INF){ return INF; } if(i){ res+=dist[t]; } for(int j=1;j<=n;j++){ dist[j]=min(dist[j],g[t][j]); } st[t]=true; } return res; } int main(){ memset(g,0x3f,sizeof(g)); cin>n>>m; while(m--){ cin>>a>>b>>c; g[a][b]=g[b][a]=min(g[a][b],c); } int t=prim(); if(prim==INF){ cout<<"impossible<<endl; } else{ cout<<t<<endl; } return 0; }
|
堆优化版O(m*logn)
不常用
克鲁斯卡尔算法(Kruskal)
稀疏图常用 O(m*logm)
①将所有边按权重从小到大排序O(m*logn)
②枚举每条边a b和权重c
if(a b不连通){
将a b这条边加入集合中
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| struct Edge{ int a,b,w; bool operator<(const Edge &W){ return w<W.w; } }edges[N];
sort(edges,edges+m);
for(int i=1;i<=n;i++){ p[i]=i; } int find(int x){ if(p[x]!=x){ p[x]=find(f[x]); } return p[x]; }
int res=0,cnt=0; for(int i=0;i<m;i++){ int a=edges[i].a,b=edges[i].b,w=edges[i].w; a=find(a),b=find(b); if(a!=b){ f[a]=b; res+=w; cnt++; } }
if(cnt!=n-1){ puts("impossible); } else{ cout<<res<<endl; }
|