最小生成树——hdu 4463

题目——————》 hdu 4463


第一次写最小生成树。粗心犯了一个错误 调啊调啊调了半个多小时

然后陷入了理所当然的思维,调了一个多小时才找到错误。

当 nike 和 apple 这条路是一定需要修建的 所以一开始我就把这两个顶点给直接排除掉了

然而 就也许会导致错误。啊 说的不清楚

直接看代码

我好饿。。。。先去吃饭 稍后补注释

用的是prim算法 之后会再补上k算法

#include<iostream>
#include<cstdio>
#include<cmath>
#include<iomanip>
using namespace std;


struct Node  //节点
{
	int x;
	int y;
};

Node node[52];

typedef struct graph{   //图
	Node *vexs;
	double matrix[52][52];  //用于记录i与j之间的权值
};

graph g;

double calculate(int x1, int x2, int y1, int y2){
	return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2));
}

void createGraph(int n){  //创建全连通图
	g.vexs = node;
	double l;
	for (int i = 1; i <= n; i++){
		g.matrix[i][i] = 0;
		for (int j = i+1; j <= n; j++){
			l = calculate(node[i].x, node[j].x, node[i].y, node[j].y);
			g.matrix[i][j] = g.matrix[j][i] = l;
		}
	}
}

double prim(int nike,int apple,int n){
	int i,j,k;
	double weights[52];               //此可以数组理解为 对于要加入当前节点时边的权值
	double sum = g.matrix[nike][apple];
	for (i = 1; i <= n; i++){                     //将nike和apple这条加入,并且更新数组 
		weights[i] = g.matrix[apple][i];
		if (weights[i] > g.matrix[nike][i]){
			weights[i] = g.matrix[nike][i];
		}
	}
	weights[nike] = 0;

	
	for (i = 3; i <= n; i++){

		double min = 100000;
		for (j = 1; j <= n; j++){
			if (weights[j] != 0 && weights[j] < min){
				min = weights[j];
				k = j;
			}
		}
		sum += min;
		weights[k] = 0;
		for (j = 1; j <= n; j++){
			if (weights[j] != 0 && g.matrix[k][j] < weights[j]){
				weights[j] = g.matrix[k][j];
			}
		}
	}
	return sum;
}

int main(){

//	freopen("TestDate.txt", "r", stdin);

	int n;
	int index_Nike;
	int index_Apple;
	while (cin >> n && n != 0){
		cin >> index_Nike >> index_Apple;

		for (int i = 1; i <= n; i++){
			cin >> node[i].x >> node[i].y;
		}



		createGraph(n);

		double result = prim(index_Nike, index_Apple, n);

		cout << fixed << setprecision(2) << result << endl;

	}
	return 0;
}

补充K算法。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
using namespace std;

#define MAX 52

struct Node
{
	int x;
	int y;
};

Node node[MAX];

struct Edge
{
	int index_a;
	int index_b;
	double weight;
};

Edge edge[MAX*(MAX - 1)];

double calculate(int x1, int x2, int y1, int y2){
	return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2));
}

int createEdge(int n){
	int i, j ,k;
	k = 0;
	for (i = 1; i <= n; i++){
		for (j = i; j <= n; j++){
			edge[k].index_a = i;
			edge[k].index_b = j;
			edge[k].weight = calculate(node[i].x, node[j].x, node[i].y, node[j].y);
			k++;
		}
	}
	return k;
}

bool compare(Edge a, Edge b){
	return a.weight < b.weight;
}

int get_end(int vends[], int start){
	int k = start,j = start;
	while (vends[k] != k){
		k = vends[k];
	}
	int swap;
	while (vends[j] != k){
		swap = vends[j];
		vends[j] = k;
		j = swap;
	}
	return k;
}

double kruskal(int nike,int apple,int edgenum,int n){
	double result = 0;
	int vends[MAX];

	int i;

	for (i = 1; i <= n; i++){
		vends[i] = i;
	}

	for (i = 0; i < edgenum; i++){
		if ((edge[i].index_a == nike && edge[i].index_b == apple) || (edge[i].index_a == apple && edge[i].index_b == nike)){
			result += edge[i].weight;
			vends[nike] = apple;
			vends[apple] = apple;
			edge[i].weight = 0;
			break;
		}
	}

	sort(edge, edge + edgenum, compare);

	int k1, k2;
	for (i = 0; i < edgenum; i++){
		if (edge[i].weight == 0){
			continue;
		}
		k1 = get_end(vends, edge[i].index_a);
		k2 = get_end(vends, edge[i].index_b);
		if (k1 != k2){
			vends[k1] = k2;
			result += edge[i].weight;
		}
	}

	return result;
}

int main(){
	freopen("TestDate.txt","r",stdin);
	int n;
	int index_Nike;
	int index_Apple;
	while (cin >> n && n != 0){
		cin >> index_Nike >> index_Apple;
		                                                                                                                               
		for (int i = 1; i <= n; i++){
			cin >> node[i].x >> node[i].y;
		}

		int edgenum = createEdge(n);

		
		double result = kruskal(index_Nike, index_Apple, edgenum,n);

		cout << fixed << setprecision(2) << result << endl;

	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值