最小生成树算法模板
以下模板全部依据 此模板题 给出,一定要理解模板,具体题目请具体分析,不要死搬硬套
另外,图论(最短路问题只是图论的一小部分)中一般有如下约定:
•nnn 表示顶点数,mmm 表示边数
•V/v(vertex)V/v(vertex)V/v(vertex) 表示顶点,E/e(edge)E/e(edge)E/e(edge) 表示边
•uuu 表示起点(也叫源点),vvv 表示终点(也叫汇点),www 表示边权
最小生成树算法模板目录
•Prim算法(包括朴素版和堆优化版)
•Kruskal算法
Prim算法(包括朴素版和堆优化版)
算法原理:贪心
朴素版
时间复杂度:O(n2)O(n^2)O(n
2
)
空间复杂度:O(n2)O(n^2)O(n
2
)(因为用邻接矩阵存图)
模板题AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=5e3+5,MAX=0x3f3f3f3f;
int n,m,from,to,w,dist[N],map[N][N];
bool st[N];
int Prim(){
memset(dist,0x3f,sizeof(dist));
int t=1,res=0;
dist[1]=0,st[1]=true;
for(int i=0;i<n-1;i++){
for(int j=1;j<=n;j++) dist[j]=min(dist[j],map[t][j]);
t=-1;
for(int j=1;j<=n;j++) if(!st[j]&&(t==-1||dist[t]>dist[j])) t=j;
if(dist[t]==MAX) return MAX;
res+=dist[t];
st[t]=true;
}
return res;
}
int main(){
cin>>n>>m;
memset(map,0x3f,sizeof(map));
while(m--){
cin>>from>>to>>w;
map[from][to]=map[to][from]=min(map[from][to],w);
}
int ans=Prim();
if(ans==MAX) cout<<"orz"<<endl;
else cout<<ans<<endl;
return 0;
}
堆优化版
时间复杂度:O(mlogn)O(mlogn)O(mlogn)
空间复杂度:O(m)O(m)O(m)(因为用邻接表存图)
模板题AC代码1(邻接表的实现方式:链式前向星——用数组模拟单链表):
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N=5e3+5,M=4e5+5,MAX=0x3f3f3f3f;
typedef pair<int,int> P;
int n,m,from,to,w,dist[N];
int h[N],v[M],nv[M],e[M],id;
bool st[N];
void add(int from,int to,int w){
v[id]=to,nv[id]=h[from],e[id]=w,h[from]=id++;
}
int Prim(){
memset(dist,0x3f,sizeof(dist));
priority_queue<P,vector<P>,greater<P> > heap;
int res=0,cnt=0;
dist[1]=0;
heap.push({0,1});
while(heap.size()){
P t=heap.top();
heap.pop();
int ver=t.second,dis=t.first;
if(st[ver]) continue;
st[ver]=true,res+=dis,cnt++;
for(int i=h[ver];i!=-1;i=nv[i]){
int j=v[i];
if(!st[j]&&dist[j]>e[i]) dist[j]=e[i],heap.push({dist[j],j});
}
}
if(cnt<n) res=MAX;
return res;
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof(h));
while(m--){
cin>>from>>to>>w;
add(from,to,w),add(to,from,w);
}
int ans=Prim();
if(ans==MAX) cout<<"orz"<<endl;
else cout<<ans<<endl;
return 0;
}
模板题AC代码2(邻接表的实现方式:STLSTLSTL 里的 vectorvectorvector 容器):
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N=5e3+5,M=4e5+5,MAX=0x3f3f3f3f;
typedef pair<int,int> P;
int n,m,from,to,w,dist[N];
vector<P> e[N];
bool st[N];
void add(int from,int to,int w){
e[from].push_back({to,w});
}
int Prim(){
memset(dist,0x3f,sizeof(dist));
priority_queue<P,vector<P>,greater<P> > heap;
int res=0,cnt=0;
dist[1]=0;
heap.push({0,1});
while(heap.size()){
P t=heap.top();
heap.pop();
int ver=t.second,dis=t.first;
if(st[ver]) continue;
st[ver]=true,res+=dis,cnt++;
for(auto x:e[ver]){
int u=x.first,d=x.second;
if(!st[u]&&dist[u]>d) dist[u]=d,heap.push({dist[u],u});
}
}
if(cnt<n) res=MAX;
return res;
}
int main(){
cin>>n>>m;
while(m--){
cin>>from>>to>>w;
add(from,to,w),add(to,from,w);
}
int ans=Prim();
if(ans==MAX) cout<<"orz"<<endl;
else cout<<ans<<endl;
return 0;
}
Kruskal算法
算法原理:贪心
时间复杂度:O(mlogm)O(mlogm)O(mlogm)
空间复杂度:O(m)O(m)O(m)
模板题AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=5e3+5,M=4e5+5,MAX=0x3f3f3f3f;
int n,m,pre[N];
struct E{
int from,to,w;
}e[M];
bool cmp(E a,E b){
return a.w<b.w;
}
int find(int x){
return pre[x]==x?x:pre[x]=find(pre[x]);
}
int Kruskal(){
for(int i=1;i<=n;i++) pre[i]=i;
sort(e,e+m,cmp);
int res=0,cnt=0;
for(int i=0;i<m;i++){
int u=e[i].from,v=e[i].to,w=e[i].w;
u=find(u),v=find(v);
if(u==v) continue;
pre[u]=v,cnt++,res+=w;
}
if(cnt<n-1) res=MAX;
return res;
}
int main(){
cin>>n>>m;
for(int i=0;i<m;i++) cin>>e[i].from>>e[i].to>>e[i].w;
int ans=Kruskal();
if(ans==MAX) cout<<"orz"<<endl;
else cout<<ans<<endl;
return 0;
}