zoukankan      html  css  js  c++  java
  • 数据结构-造树计划-最小生成树

    最小生成树

    思路

    • 沿某一点绕一圈,遇到最小的点往路径最小的点走

    • 并用p[]数组来记录该点的父结点

      p[v]=u(表示v的父节点是u),方便求出路径和sum+=G[i][p[i]]

    • 如果说p[v]=提前设定好的值,也就是说它没有被改变,那么要么这个点是出发点,要么这个点是被“隔离”的。

    • 加强理解的手段,用color数组,取三个值分别表示已经被用(BLACK),要被用(GRAY)和还没有探索到(WHITE)

    • 确定新起点(注意原起点打通了与新起点的通道(使得这些点变成了灰色(缓冲点)),d[v]=d[u][v]

    • 注意:可能还要考虑重边和自环

    AC代码P3366 【模板】最小生成树

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    static const int MAX=5005;
    static const int WHITE=0;//表示未用过的点 
    static const int GREY=1;//表示待用的点 
    static const int BLACK=2;//表示用过的点 
    static const int INFTY=999999;
    int G[MAX][MAX];
    int p[MAX];
    int color[MAX];
    int d[MAX];
    int num,n;
    void prim()
    {
    	//初始化
    	for(int i=1;i<=num;i++)
    	{
    		p[i]=-1;
    	    color[i]=WHITE;	
    	    d[i]=INFTY; 
    	} 
    	
    	d[1]=0;
    	
    	
    	while(1)
    	{
    		int u=-1;
    		int minv=INFTY;
    		
    	//	cout<<2<<endl;
    		for(int i=1;i<=num;i++)
    		{	
    		  //  cout<<3<<endl;
    			if(d[i]<minv&&color[i]!=BLACK)
    			{
    	//			cout<<4<<endl;
    				
    				u=i;
    	//			cout<<u<<endl;
    				minv=d[i];
    			}
    		}
    		
    		if(u==-1)break;
    		
    		color[u]=BLACK;
    		
    		for(int v=1;v<=num;v++)
    		{
    			if(color[v]!=BLACK&&d[v]>G[u][v]&&u!=v)
    			{
    				color[v]=GREY;
    				d[v]=G[u][v];
    				p[v]=u;
    			}
    		}
    	}
    	
    	int total=0;
    	int flag=1; 
    	for(int v=2;v<=num;v++)
    	{
    	//	cout<<6<<endl;
    		if(p[v]==-1)
    		{
    			flag=0;
    			cout<<"orz";
    			break;
    		}
    		total+=G[v][p[v]];
    	//	cout<<p[v]<<"     "<<G[v][p[v]]<<"     "<<total<<endl;
    	}
    	if(flag)cout<<total;
    }
    int main()
    {
    	cin>>num>>n;
    	
    	for(int i=1;i<=num;i++)
    	{
    		for(int j=1;j<=num;j++)
    		{
    			G[i][j]=INFTY;
    			G[j][i]=INFTY;
    		}
    	}
    	
    	for(int i=1;i<=n;i++)
    	{
    		int s,t,e;
    		cin>>s>>t>>e;
    		if(G[s][t]>=e)
    		{
    		G[s][t]=e;
    		G[t][s]=e;
    		}
    		//cout<<G[s][t];
    	}
    	prim();
    	
    	return 0;
    }
    

    其他

    距离无穷大

    static const int INFTY =(1<<21);

    参考资料

    1. 挑战程序设计竞赛

    2. zjl大佬

    3. 洛谷链接

  • 相关阅读:
    找出占用磁盘空间最大的前10个文件或文件夹
    把inline函数的定义放在头文件中
    判断是大端字节序还是小端字节序
    在source insight 中添加系统字体
    C++ inline 函数
    标准I/O函数库的三类缓冲
    内存分配失败错误处理
    P1765 手机
    P1321 单词覆盖还原
    P1308 [NOIP2011 普及组] 统计单词数
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/14532122.html
Copyright © 2011-2022 走看看