HDU 3道最小生成树题目

//hdu1879 还是畅通工程

#include <iostream>

#include <algorithm>

#define  MAX 5000

using namespace std;



int father[MAX];

int my_rank[MAX];



void make_set()

{

	for (int i = 0; i < MAX; i++)

	{

		my_rank[i] = 0;

		father[i] = i;

	}

}



int find_set(int x)

{

	if (x != father[x])

		father[x] = find_set(father[x]);



	return father[x];

}



void union_set(int x, int y)

{

	x = find_set(x);

	y = find_set(y);



	if (x == y) return;



	if (my_rank[x] > my_rank[y])

		father[y] = x;

	else

	{

		father[x] = y;

		if (my_rank[x] == my_rank[y])

			my_rank[y]++;

	}



}



struct edge

{

	int begin;

	int end;

	int weight;

};



int N,M;



edge e[MAX];



bool cmp(const edge& a, const edge& b)

{

	return a.weight < b.weight;

}



int main()

{

	int count, result;

	int x, y;

	bool isbuild;



	while (cin >> N && N)

	{

		M = N*(N-1)/2;

		make_set();



		for (int i = 0; i < M; i++)

		{

			cin >> e[i].begin >> e[i].end >> e[i].weight >> isbuild;

			if (isbuild)

			{

				x = find_set(e[i].begin);

				y = find_set(e[i].end);

				if (x != y)

					union_set(x, y);

			}

		}



		sort(e, e+M, cmp);

		count = 0;

		result = 0;



		while (count != M)

		{



			x = find_set(e[count].begin);

			y = find_set(e[count].end);



			if (x != y)

			{

				union_set(x, y);

				result += e[count].weight;

			}

			count++;

		}

		cout << result << endl;

	}

	return 0;

}

//1863畅通工程

#include<iostream>

#include <algorithm>

#define  MAX 105

using namespace std;



int father[MAX];

int my_rank[MAX];



void make_set()

{

	for (int i = 0; i < MAX; i++)

	{

		my_rank[i] = 0;

		father[i] = i;

	}

}



int find_set(int x)

{

	if (x != father[x])

		father[x] = find_set(father[x]);



	return father[x];

}



void union_set(int x, int y)

{

	x = find_set(x);

	y = find_set(y);



	if (x == y) return;



	if (my_rank[x] > my_rank[y])

		father[y] = x;

	else

	{

		father[x] = y;

		if (my_rank[x] == my_rank[y])

			my_rank[y]++;

	}



}



struct edge

{

	int begin;

	int end;

	int weight;

};



int N,M;



edge e[MAX];



bool cmp(const edge& a, const edge& b)

{

	return a.weight < b.weight;

}



int main()

{

	int count, result;

	int x, y;



	while (cin >> N && N)

	{

		cin >> M;

		for (int i = 0; i < N; i++)

			cin >> e[i].begin >> e[i].end >> e[i].weight;



		sort(e, e+N, cmp);



		count = 0;

		result = 0;



		make_set();

		while (count != N)

		{



			x = find_set(e[count].begin);

			y = find_set(e[count].end);



			if (x != y)

			{

				union_set(x, y);

				result += e[count].weight;

			}

			count++;

		}



		count = 0;

		for (int i = 1; i <= M; i++)

		{

			if (father[i] == i) count++;

		}



		if (count == 1)

			cout << result << endl;

		else

			cout << "?" << endl;



	}

	return 0;

}





//1875畅通工程再续

//这题注意精度问题,要先计算开根号的值,然后在最小生成树时在加起来

//不可先保存没开平方的值,一开始我保存的是没开根号,得到最后答案后再开根号,认为这会准确些

//后来WA卡住了,后来实际想不同就和别人解题报告一比,发现了这个问题

#include <iostream>

#include <algorithm>

#include <math.h>

#include <stdio.h>

#define MAX 6000

using namespace std;



int father[MAX];

int my_rank[MAX];



void make_set()

{

	for (int i = 0; i < MAX; i++)

	{

		father[i] = i;

		my_rank[i] = 0;

	}

}



int find_set(int x)

{

	if (x != father[x])

		father[x] = find_set(father[x]);



	return father[x];

}



void union_set(int x, int y)

{

	x = find_set(x);

	y = find_set(y);



	if (x == y) return;



	if (my_rank[x] > my_rank[y])

		father[y] = x;

	else

	{

		father[x] = y;



		if (my_rank[x] == my_rank[y])

			my_rank[y]++;

	}

}



struct coordinate

{

	int x, y;

	int id;

};



struct edge

{

	int begin_id;

	int end_id;

	double weight;

};



edge e[MAX];

coordinate point[MAX];



bool cmp(const edge& a, const edge& b)

{

	return a.weight < b.weight;

}



int main()

{

	int cases;

	int n;

	int count;

	double distances;



	cin >> cases;

	while (cases--)

	{

		cin >> n;



		for (int i = 0; i < n; point[i].id = i,i++)

			cin >> point[i].x >> point[i].y;



		count = 0;

		for (int i = 0; i < n; i++)

		{

			for (int j = i+1; j < n; j++)

			{

				distances = sqrt((double)((point[i].x-point[j].x)*(point[i].x-point[j].x) + (point[i].y-point[j].y)*(point[i].y-point[j].y)));

				if (distances >= 10.0 && distances <= 1000.0)

				{

					e[count].begin_id = point[i].id;

					e[count].end_id = point[j].id;

					e[count].weight = distances;

					count++;

				}

			}

		}



		sort(e, e+count, cmp);



		int m = 0;

		make_set();

		int x, y;

		double result = 0;



		while (m != count)

		{

			x = find_set(e[m].begin_id);

			y = find_set(e[m].end_id);



			if (x != y)

			{

				union_set(x, y);

				result += e[m].weight;

			}



			m++;

		}



		int count = 0;

		for (int i = 0; i < n; i++)

			if (point[i].id == father[point[i].id])

				count++;



		if (count == 1)

			printf("%.1lf\n", result*100);

		else

			cout << "oh!" << endl;

	}

	return 0;

}

你可能感兴趣的:(最小生成树)