最小生成树
最小生成树
\(Kruskal\)
很简单的贪心求最小生成树。
按边权排序,从前往后枚举边,只要这条边的两个点不在一个集合里,就将他加入答案,同时合并该边连接的两个点。并查集维护一下就好了
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,f[5005],ans;
bool b;
struct line{
int from,next,dis;
}a[200005];
int find(int x){
return f[x]==x? x:f[x]=find(f[x]);
}
void unionn(int a,int b){
int x=find(f[a]),y=find(f[b]);
if(x!=y) f[x]=f[y];
}
bool cmp(line a,line b){
return a.dis<b.dis;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++)
cin>>a[i].from>>a[i].next>>a[i].dis;
sort(a+1,a+1+m,cmp);
for(int i=1;i<=m;i++){
int x=find(a[i].from),y=find(a[i].next);
if(x!=y) ans+=a[i].dis,unionn(x,y);
}
for(int i=1;i<n;i++)
if(find(i)!=find(i+1)){
b=1;break;
}
if(b) cout<<"orz"<<endl;
else cout<<ans<<endl;
return 0;
}
\(prim\)
我总是会忍不住加个\(e\)
反正这个我从来没写过
#include<iostream>
using namespace std;
int n,m,w[5001][5001],dis[5001],ans,minn,k,x,y,z;
void prime(int s){
for(int i=1;i<=n;i++) dis[i]=w[s][i];
dis[s]=0;
for(int i=1;i<n;i++){
minn=999999999;
for(int j=1;j<=n;j++)
if(dis[j]&&dis[j]<minn)
minn=dis[j],k=j;
dis[k]=0,ans+=minn;
for(int j=1;j<=n;j++)
if(w[k][j]<dis[j])
dis[j]=w[k][j];
}
printf("%d",ans);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
w[i][j]=999999999;
for(int i=1;i<=m;i++){
cin>>x>>y>>z;
if(z<w[x][y]) w[y][x]=w[x][y]=z;
}
prime(n>>1);
return 0;
}
欢迎指正评论O(∩_∩)O~~