最小生成树

最小生成树

\(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~~

posted @ 2018-10-30 19:04  Kylin_Seven  阅读(144)  评论(0编辑  收藏  举报