はなたの日記

ギターのコードについて書きます

ALDS1_12_A Minimum Spanning Tree(プリムのアルゴリズム)

問題
最小全域木| アルゴリズムとデータ構造 | Aizu Online Judge

前回と同じ問題です。今度はプリムのアルゴリズムで解いてみました。
やはりこちらのレジュメが分かり易かったです。
http://www.dais.is.tohoku.ac.jp/~shioura/teaching/ad09/ad09-10.pdf

ヒープの要素は、「ノード番号」と「0番からのコスト」をまとめた構造体です。
「ヒープの要素がなくなる」⇔「全ての頂点が選ばれた」ってことです。
クラスカル法では、unionfindで閉路になってないかどうか調べていたのですが、プリムのでは調べる必要がありません!便利!

#include<stdio.h>
#include<stdlib.h>
#define N 100
#define INF 1000000
#define MIN(a, b) ((a) < (b) ? (a) : (b))

int a[N][N];

typedef struct node{
	int id;
	int cost;
}node;

void swap(node h[],int x,int y){
	node temp=h[x];
	h[x]=h[y];
	h[y]=temp;
	return;
}


void heapsort(node heap[],int num){

	for(int i=num-1;i>0;i--){
		if(i%2==0){
			if(heap[i].cost < heap[i/2-1].cost)swap(heap,i,i/2-1);
		}else {
			if(heap[i].cost < heap[i/2].cost)swap(heap,i,i/2);
		}
	}
	
	return;

}

int update_heap(node heap[],int num){
	int u=heap[0].id;
	swap(heap,0,num-1);
	num--;
	
	for(int i=0;i<num;i++){
		heap[i].cost=MIN(heap[i].cost,a[u][heap[i].id]);
	}
	
	return num;
}




int main(){
	int i,j,n;
	int num=0;/*heapの要素の個数*/
	int ans=0;
	node heap[N];
	
	
	scanf("%d",&n);
	
	
	/*隣接行列の読み込み*/
	for(i=0;i<n;i++){
		for(j=0;j<n;j++){
			scanf("%d",&a[i][j]);
			if(a[i][j]==-1)a[i][j]=INF;
		}
	}
	
	/*0以外の頂点をinsert*/
	for(i=1;i<n;i++){
		heap[num].cost=a[0][i];
		heap[num++].id=i;
	}
	
	/*heapを昇順にソート*/
	heapsort(heap,num);
	
	while(num!=0){
		ans+=heap[0].cost;
		num=update_heap(heap,num);
		heapsort(heap,num);
	}
	
	printf("%d\n",ans);
	
	return 0;
	
}

一回でacceptされたので嬉しかったです。