【题解】洛谷P1546 最短网络(最小生成树)

Kruskal算法的步骤包括:

1. 对所有权值进行从小到大排序(这里对边排序时还需要记录边的索引,这样以边的权值排完序后只改变了权值的索引位置)

2. 然后每次选取最小的权值,如果和已有点集构成环则跳过,否则加到该点集中。最终有所有的点集构成的树就是最佳的。

#include <cstdio>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define maxn 100010
using namespace std;

int n;
int a;
struct edge
{
    int u;
    int v;
    int w;	
};
struct edge e[maxn];

int f[101]={0},sum=0;

bool cmp(edge a,edge b)
{
    return a.w<b.w;
}

int find(int x)
{
    if(f[x]==x) return x;
    else
    {
        f[x]=find(f[x]);
        return f[x];
    }
}

int merge(int v,int u)
{
    int t1=find(v);
    int t2=find(u);
    if(t1!=t2)
    {
        f[t2]=t1;
        return 1;
    }
    return 0;
}

int main()
{
    scanf("%d",&n);
    int cnt;
    int count; 
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&a);
            if(i==j) continue;		
            e[++cnt].u=i;
            e[cnt].v=j;
            e[cnt].w=a;
        }
    }
    sort(e+1,e+cnt+1,cmp);
    for(int i=1;i<=cnt;i++)
    {
        if(find(e[i].u)!=find(e[i].v))
        {
            if(merge(e[i].u,e[i].v))
            {
                count++;
                sum+=e[i].w;
            }
            if(count==n-1)
            {
                break;
            }
        }
    }
    
    printf("%d",sum);
    return 0;
}

Prim算法的步骤包括:

1. 将一个图分为两部分,一部分归为点集U,一部分归为点集V,U的初始集合为{V1},V的初始集合为{ALL-V1}。

2. 针对U开始找U中各节点的所有关联的边的权值最小的那个,然后将关联的节点Vi加入到U中,并且从V中删除(注意不能形成环)。

3. 递归执行步骤2,直到V中的集合为空。

4. U中所有节点构成的树就是最小生成树。

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=110;
int e[maxn][maxn],dis[maxn];
bool b[maxn];
int ans=0;
int n;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>e[i][j];
		}
	}
	
	int u,minn;
	
	for(int i=1;i<=n;i++)
	{
		b[i]=false;
	}b[1]=true;
	
	for(int i=1;i<=n;i++)
	{
		dis[i]=e[1][i];
	}
	
	for(int i=1;i<=n;i++)
	{
		minn=1e9;
		for(int j=1;j<=n;j++)
		{
			if(b[j]==false&&minn>dis[j])
			{
				minn=dis[j];
				u=j;
			}
		}
		if(minn==1e9) break;
		ans+=minn;
		b[u]=true;
		for(int v=1;v<=n;v++)
		{
			if(b[v]==false&&dis[v]>e[u][v])
			{
				dis[v]=e[u][v];
			}
		}
	}
	
	cout<<ans<<endl;
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81138705
今日推荐