对最小生成树算法的总结

最小生成树只会两个算法:Prim和Kruskal。

Kruskal用到了排序+并查集,并且只n个顶点最多需要n-1条边即退出

#include
using namespace std;
const int maxn=1e5+10;
int rank[maxn],parent[maxn],ans,n,m;//rank用来压缩路径,parent用来存放父节点; 
struct person
{
	int x;//位置1 
	int y;//位置2 
	int v;//两位置的权值 
} p[maxn];
bool cmp(person a,person b)
{
	return a.vrank[y])parent[y]=x;
	else if(rank[x]>n>>m;
	clear(n);
	for(int i=0; i>p[i].x>>p[i].y>>p[i].v;
	sort(p,p+m,cmp);
	kuskal();
	cout<

Prim

Prim算法跟dj算法很像很像,都是一次循环找出一个顶点,然后利用该顶点去扩展其他的待定顶点加入到队列中,鄙人认为这两个算法的不同之处在于prim算法的dis数组的意义在于其他未进入生成树的顶点到生成树的距离,这一点很重要,因为重点在于未进入生成树的点的值对应的不是生成树中的某个点,而是整个树

然后dj算法是着重于dis数组里面已经确地的值,通过这些值去寻找接下来的待定值

#include
#define INF 10000
using namespace std;
constint N = 6;
bool visit[N];
intdist[N] = { 0, };
intgraph[N][N] = { {INF,7,4,INF,INF,INF},  //INF代表两点之间不可达
                    {7,INF,6,2,INF,4},
                    {4,6,INF,INF,9,8},
                    {INF,2,INF,INF,INF,7},
                    {INF,INF,9,INF,INF,1},
                    {INF,4,8,7,1,INF}
                  };
int prim(int cur)
{
    intindex = cur;
    intsum = 0;
    inti = 0;
    intj = 0;
    cout << index << " ";
    memset(visit,false, sizeof(visit));
    visit[cur] = true;
    for(i = 0; i < N; i++)
        dist[i] = graph[cur][i];//初始化,每个与a邻接的点的距离存入dist
    for(i = 1; i < N; i++)
    {
        int minor = INF;
        for(j = 0; j < N; j++)
        {
            if(!visit[j] && dist[j] < minor)          //找到未访问的点中,距离当前最小生成树距离最小的点
            {
                minor = dist[j];
                index = j;
            }
        }
        visit[index] = true;
        cout << index << " ";
        sum += minor;
        for(j = 0; j < N; j++)
        {//更新一个点index,就从index开始出其他新的dist 
            if(!visit[j] && graph[index][j]

prim算法堆优化

#include
#include
#include
#include
#include
using namespace std;
//n个顶点m条路
const int maxn=1e3;//m的范围
const int maxm=100+10;//顶点个数
const int INF=0x3f3f3f;
struct node
{
	int next,to,val;
} edge[maxn];
int head[maxm],cnt,n,m,dis[maxm],vis[maxm],res;
void add(int x,int y,int val)
{
	edge[++cnt].val=val;
	edge[cnt].to=y;
	edge[cnt].next=head[x];
	head[x]=cnt;
}
void prim(int cur)
{
	int res=0;
	memset(vis,0,sizeof(vis));
	for(int i=1; i<=m; i++)
	{
		dis[i]=INF;
		vis[i]=0;
	}
	dis[cur]=0;
	priority_queue,vector >,greater > > q;
	q.push(make_pair(0,cur));
	while(!q.empty())
	{


		int temp=q.top().second;
		q.pop();
		if(vis[temp])continue;
		vis[temp]=1;



		res+=dis[temp];
		//cout<edge[j].val)
			{
				dis[edge[j].to]=edge[j].val;
				q.push(make_pair(dis[edge[j].to],edge[j].to));
			}
		}
	}
	for(int i=1; i<=m; i++)

		if(!vis[i])
		{
			cout<<"?"<>n;
		if(n==0)break;
		cin>>m;
		int u,v,weight;
		cnt=1;
		for(int i=1; i<=n; i++)
		{
			scanf("%d%d%d",&u,&v,&weight);
			add(u,v,weight);

		}


		prim(1);

	}
	return 0;
}
#include
#include
#include
#include
#include
using namespace std;
//n个顶点m条路
const int maxn=1e5;//m的范围
const int maxm=1e5+10;//顶点个数
const int INF=0x3f3f3f;
struct node
{
	int next,to,val;
} edge[maxn];
int head[maxm],cnt,n,m,dis[maxm],vis[maxm],res,flag;
void add(int x,int y,int val)
{
	edge[cnt].val=val;
	edge[cnt].to=y;
	edge[cnt].next=head[x];
	head[x]=cnt++;
}
void prim(int cur)
{
	int res=0;

	for(int i=1; i<=n; i++)
	{
		dis[i]=INF;
		vis[i]=0;
	}
	for(int i=head[cur]; i; i=edge[i].next)
	//	dis[edge[i].to]=min(edge[i].val,dis[edge[i].to]);
		dis[edge[i].to]=edge[i].val;
	//	for(int i=1;i<=n;i++)
	//	printf("i==%d  dis[i]==%d\n",i,dis[i]);
	dis[cur]=0;
	vis[cur]=1;
	int j=1;
	for( j=1; jedge[i].val)
				dis[edge[i].to]=edge[i].val;
		}
	}


	if(j>m;
		if(m==0)break;
		cin>>n;
		int u,v,weight;
		cnt=1;
		memset(edge,0,sizeof(edge));
		memset(head,0,sizeof(head));
		for(int i=1; i<=m; i++)
		{
			scanf("%d%d%d",&u,&v,&weight);
			add(u,v,weight);
			add(v,u,weight);

		}


		prim(1);

	}
	return 0;
}

prim算法跟最短路的dj算法最不一样的地方在于

for(int i=head[flag]; i; i=edge[i].next)
        {
            if(!vis[edge[i].to]&&dis[edge[i].to]>edge[i].val)
                dis[edge[i].to]=edge[i].val;
        }

dj的是for(int i=head[flag]; i; i=edge[i].next)
        {
            if(!vis[edge[i].to]&&dis[edge[i].to]>dis[tem]+edge[i].val)
                dis[edge[i].to]=edge[i].val+dis[temp];
        }

注意这个dis【temp】在prim算法中是没有的

还有要注意重边和有无方向

你可能感兴趣的:(最小生成树)