山东大学数据结构实验十三

最小生成树(Kruskal和Prim算法)

描述
分别使用prim和kruskal算法实现最小生成树
输入
格式:
第一行两个整数n,e。n (2000001≤n≤200000) 代表图中点的个数,e (5000000≤m≤500000) 代表边的个数。
接下来e行,每行代表一条边:

i j w 表示顶点i和顶点j之间有一条权重为w的边

输出
最小生成树所有边的权重和

  • test 13-1
#include
#include
using namespace std;
struct edge
{
    long long to;
    long long w;
};

struct edge1
{
	long long w;
	long long v;
    edge1(){}//注意默认构造函数一定要写
    edge1(int w1,int v1){
        w=w1,v=v1;
    }
	bool operator < (const edge1& b) const
	{
		return w < b.w;
	}
    bool operator <= (const edge1& b) const
	{
		return w <= b.w;
	}
    bool operator > (const edge1& b) const
	{
		return w > b.w;
	}
};
    vector<edge> edges[200005];//可用链表数组代替
    bool lowcost[200005];
//接下来是最小堆的实现
template<class T>
void changeLength1D(T*& a, int oldLength, int newLength)
{
    T* temp = new T[newLength];              
    int number = min(oldLength, newLength);  
    copy(a, a + number, temp);
    delete[] a;                          
    a = temp;
}
template<class T>
class minHeap
{
public:
    minHeap(int initialCapacity = 10);
    ~minHeap() { delete[] heap; }
    bool empty() const { return heapSize == 0; }
    int size() const
    {
        return heapSize;
    }
    const T top()
    {
        return heap[1];
    }
    void pop();
    void push(const T&);
    void initialize(T*, int);
    void deactivateArray()
    {
        heap = NULL; arrayLength = heapSize = 0;
    }
private:
    int heapSize;     
    int arrayLength;    
    T* heap;            
};

template<class T>
minHeap<T>::minHeap(int initialCapacity)
{
    arrayLength = initialCapacity + 1;
    heap = new T[arrayLength];
    heapSize = 0;
}

template<class T>
void minHeap<T>::push(const T& theElement)
{

    if (heapSize == arrayLength - 1)
    {
        changeLength1D(heap, arrayLength, 2 * arrayLength);
        arrayLength *= 2;
    }

    int currentNode = ++heapSize;
    while (currentNode != 1 && heap[currentNode / 2] > theElement)
    {
        heap[currentNode] = heap[currentNode / 2]; 
        currentNode /= 2;
    }

    heap[currentNode] = theElement;
}

template<class T>
void minHeap<T>::pop()
{
    heap[1].~T();

    T lastElement = heap[heapSize--];
    int currentNode = 1,
        child = 2;     
    while (child <= heapSize)
    {
        if (child < heapSize && heap[child] > heap[child + 1])
            child++;
        if (lastElement <= heap[child])
            break;   

        heap[currentNode] = heap[child];
        currentNode = child;             
        child *= 2;
    }
    heap[currentNode] = lastElement;
}


class Prime{
public:
    void initialize(){
    cin >> n >> e;
    for( int i = 0; i <= n; ++i)
		lowcost[i] = true;//用来判断是否该点已经加入
    for(int i = 1; i <= e; ++i)
    {
        long long v1, v2, w;
        cin >> v1 >> v2 >> w;
        edge e1,e2;
        e1.w=w,e2.w=w;
        e1.to=v2,e2.to=v1;
        edges[v1].push_back(e1);
        edges[v2].push_back(e2);
    }
    }
    void prim()
{
    long long s = edges[1].size();//获取第一个数组的长度
    minHeap<edge1> q;
    lowcost[1] = 0;
    for(int i = 0; i < s; ++i)//初始化相邻点
    {
        long long v = edges[1][i].to, w = edges[1][i].w;
        edge1 temp(w,v);
        q.push(temp);
    }
    
    for(int i = 1; i <= n - 1; ++i)
    {
        long long min, toVetx;
    	while(lowcost[q.top().v] == 0)//最小堆中会加入多余的边,判断是否该点是否已经加入
			q.pop();
		min = q.top().w;
		toVetx = q.top().v;
        q.pop();
        
        result += min;//更新结果
        lowcost[toVetx] = 0;
        s = edges[toVetx].size();
        for(int j = 0; j < s; ++j)//遍历新加入的边的邻接点
        {
            long long v = edges[toVetx][j].to, w = edges[toVetx][j].w;
            if(lowcost[v])//如果该点未被加入点集
            {
                edge1 temp(w,v);
                q.push(temp);
            }
                
        }
    }
    cout<<result;
}


private:
    
    long long result=0;
    int n,e;              //顶点和边数
};

int main()
{   Prime P;
    P.initialize();
    P.prim();
    return 0;
}
  • test 13-2
#include
using namespace std;
int pre[200010];//记录所有节点的父节点
struct node
{	long long dis;
	int from,to;
}edge[500010];

void quickSort(node *array,int low,int high){
	if(low>high) return;
	int i,j;node index;
	index=array[low];i=low;j=high;
	while(i<j){
		while(i<j&&array[j].dis>=index.dis)
				j--;
	if(j>i) array[i++]=array[j];
	while(i<j&&array[i].dis<index.dis)
	i++;
	if(j>i) array[j--]=array[i];
	
	}
	array[i]=index;
	quickSort(array,low,i-1);
	quickSort(array,i+1,high);
}
int find(int x)
{
	int root=x;
	while(root!=pre[root]) root=pre[root];//找到根
	while(x!=root){//压缩路径 所有的子节点都指向根
		int temp=pre[x];
		pre[x]=root;
		x=temp;
	}
	return root;
}
void join(int x,int y)//将y祖父节点指向x的祖父节点
{
	pre[find(y)]=find(x);
	
}


int main()
{   long long sum;
	int n,m,k=0;
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{   cin>>edge[i].from>>edge[i].to>>edge[i].dis;
		int temp=0;
		if(edge[i].from>edge[i].to){//按照顺序存储
			temp=edge[i].from;
			edge[i].from=edge[i].to;
			edge[i].to=temp;
		}
	}
	for(int i=1;i<=n;i++)
	 pre[i]=i;//初始化自身为一个类
	quickSort(edge,1,m);
	for(int i=1;i<=m;i++)//遍历所有的边
	{
		if(k==n-1) break;//满足条件退出
		if(find(edge[i].from)!=find(edge[i].to))//如果不是一个集合
		{
			join(edge[i].from,edge[i].to);//合并 
			sum+=edge[i].dis;//记录边权 
			k++;//已连接边数+1 
		}
	}
	cout<<sum;
	return 0;
}

你可能感兴趣的:(数据结构,c++,算法)