最(次)小生成树

最小生成树

Prim--类似dijkstra,按最短路增广,堆优化

Kruskal--边权排序,并查集判环,加n-1条边即可

动态最小--Kruskal+插入排序 O(n^2)

//Prim 
//dis为连到最小生成树的最短距离
memset(dis,-1,sizeof(dis));
dis[1]=0,vis[1]=1;
priority_queue<pair<int,int> >q;
q.push(make_pair(0,1));//dis,pos
while(!q.empty()){
    int Dis=q.top().first,u=q.top().second;
        q.pop();
        if(vis[u])continue;
        vis[u]=1;
        ans+=Dis;
        for(i=head[u];i;i=next[i]){
            int v=to[i];
            if(!vis[v]&&(dist[v]>val[i]||dist[v]==-1)){
                dist[v]=val[i];
                q.push(make_pair(dist[v],v));
            }
        }
    }
}
//Kruskal
memset(F,-1,sizeof(F));
sort(edge,edge+tol,cmp);
int cnt=0;//计算加入的边数
int ans=0;
for(int i=0;i<tol;i++)
{
    int u=edge[i].u,v=edge[i].v,w=edge[i].w;
    u=Find(u),v=Find(v);
    if(u!=v)
    {
        ans+=w;
        F[u]=v;
        cnt++;
    }
    if(cnt==n-1)break;
}
动态最小生成树
#include<bits/stdc++.h>
#define N 10005
using namespace std;
int n,h,fa[N],pd,Max,sum;
struct Node{int x;int y;int w;}a[N];
int getfather(int x){//并查集
	if(fa[x]==x) return x;
	fa[x]=getfather(fa[x]);
	return fa[x];
}
void Sort(Node cur)//插入排序
{
	int i,j;
	for(i=sum;i>=1;i--) if(a[i].w<=cur.w) break;
	for(j=sum;j>=i+1;j--) a[j+1]=a[j];
	a[i+1]=cur,sum++;
}
int Kruskal()
{
	int ans=0,k=0;
	for(int i=1;i<=sum;i++) fa[i]=i;
	for(int i=1;i<=sum;i++){
		int x=getfather(a[i].x),y=getfather(a[i].y);
		if(x!=y) fa[x]=y,ans+=a[i].w,Max=a[i].w,k++;
		if(k==n-1) break;
	}
	if(k<n-1) return 0;
	return ans;
}
int main()
{
	//freopen("1.in","r",stdin);
	cin>>n>>h;
	for(int i=1;i<=h;i++){
		Node cur;
		int ans;
		cin>>cur.x>>cur.y>>cur.w;
		if(pd&&cur.w>Max){cout<<ans<<endl;continue;}//如果插入的边
        //比当前最小生成树的最大边还大,则不更新
		Sort(cur);
		if(ans=Kruskal()){cout<<ans<<endl;pd=1;}
		else cout<<"-1"<<endl;
	}
	return 0;
}

 次小生成树

int dis[N],used[N][N];//到最小生成树最短的距离
int vis[N],Map[N][N],Max[N][N];
//Map存边权,Max指i-j路径上的最大距离
int pre[N];//i的上一个点
int Prim()
{
	for(int i=2;i<=n;i++) pre[i]=1,dis[i]=Map[1][i];
	pre[1]=0,vis[1]=1,dis[1]=0;
	for(int i=2;i<=n;i++){
		int min_dis=inf,k;
		for(int j=1;j<=n;j++){
			if(!vis[j]&&min_dis>dis[j]){
				min_dis=dis[j],k=j;
			}
		} 
		if(min_dis==inf) return -1;
		vis[k]=1,ans+=min_dis;
		used[k][pre[k]]=used[pre[k]][k]=1;
		for(int j=1;j<=n;j++){
			if (vis[j]&&used[j][k]==0) Max[j][k]=Max[k][j]=max(Max[j][pre[k]],dis[k]);
			//计算两点之间若无连接,若连接上构成回路这条回路中最大的一条边,有动归的思想
			if(!vis[j]&&dis[j]>dis[k]+Map[j][k]){
				dis[j]=dis[k]+Map[j][k],pre[j]=k;
			} 
		}
    }
    return ans;
} 
int change(int min_ans)//最小生成树的权值和
{
	int ans=inf;
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
			ans=min(ans,min_ans+Map[i][j]-Max[i][j]);
	return ans;
} 

猜你喜欢

转载自blog.csdn.net/sslz_fsy/article/details/81913595
今日推荐