/*-------------------------------------------------*/
/* Minimum Spanning Tree / m8724607 / ªL²Q´D */
/* My program limit CPU_Size at 1,2,4,8,...(2^i) */
/* Its for compair and broadcast with tree algorithm */
/*-------------------------------------------------*/
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define maxV 1000 /* set max number of vertices */
#define MAX 100
#define True 1
#define False 0
int cost[maxV][maxV]; /* cost matrix of graph */
int nearest[maxV]; /* closest node matrix */
int spantree[maxV]; /* node of spanning tree */
int at_tree[maxV]; /* states of each point which on tree or no */
int rec[3], N;
int temp[3];
FILE *data;
void main(int argc, char *argv[])
{
int K, my_pe;
int i, j, k, p, par, t, c;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &K);
MPI_Comm_rank(MPI_COMM_WORLD, &my_pe);
/*-------------------------------data input and inilization-----------*/
data = fopen(argv[1],"r");
fscanf(data, "%d", &N);
for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
fscanf(data, "%4d", &cost[i][j]);
}
par = N/K;
temp[2] = 0;
nearest[0] = 0;
t=my_pe*par;
for(j=0; j<N; j++)
{
spantree[j] = 0;
at_tree[j] = False;
nearest[j] = 0;
}
spantree[0]=0;
at_tree[0]=True;
/*------------------------start for find local min----------------*/
for(k=1; k<N; k++)
{
t = my_pe*par;
temp[0] = MAX;
for(j=0; j<par; j++)
{
c=t+j;
if(at_tree[c] == False)
{
if(cost[c][nearest[c]] <= temp[0])
{
temp[0] = cost[c][nearest[c]];
temp[1] = c;
temp[2] = nearest[c];
}
}
}
/*-----------------------------start find global min ------------*/
t=1;
while(t<K)
{
if((my_pe%t)==0)
{
if((my_pe%(t*2))==0)
{
MPI_Recv(&rec, 3, MPI_INT, my_pe+t, 4, MPI_COMM_WORLD, &status);
if(temp[0] > rec[0])
{
temp[0] = rec[0];
temp[1] = rec[1];
temp[2] = rec[2];
}
}
if((my_pe%(t*2))!=0)
MPI_Send(&temp, 3, MPI_INT, my_pe-t, 4, MPI_COMM_WORLD);
}
t=t*2;
}
/*------------------boardcast abs min to each processor -----------*/
t=K;
while(t>1)
{
if((my_pe%t)==0)
MPI_Send(&temp,3,MPI_INT,my_pe+(t/2),0,MPI_COMM_WORLD);
if((my_pe%t)==(t/2))
MPI_Recv(&temp,3, MPI_INT,my_pe-(t/2) ,0, MPI_COMM_WORLD, &status);
t=t/2;
}
spantree[k] = temp[1];
at_tree[temp[1]] = True;
/*-----------------------------change some data--------------*/
i=my_pe;
for(j=0; j<par; j++)
{
t=i*par+j;
if(at_tree[t]==False)
{
if(cost[t][spantree[k]] < cost[t][nearest[t]])
nearest[t] = spantree[k];
}
}
}
MPI_Finalize();
}