POJ1751 _Highways(最小生成树——prim)

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 6078 Accepted: 1650 Special Judge

Description

The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has a very poor system of public highways. The Flatopian government is aware of this problem and has already constructed a number of highways connecting some of the most important towns. However, there are still some towns that you can't reach via a highway. It is necessary to build more highways so that it will be possible to drive between any pair of towns without leaving the highway system.

Flatopian towns are numbered from 1 to N and town i has a position given by the Cartesian coordinates (xi, yi). Each highway connects exaclty two towns. All highways (both the original ones and the ones that are to be built) follow straight lines, and thus their length is equal to Cartesian distance between towns. All highways can be used in both directions. Highways can freely cross each other, but a driver can only switch between highways at a town that is located at the end of both highways.

The Flatopian government wants to minimize the cost of building new highways. However, they want to guarantee that every town is highway-reachable from every other town. Since Flatopia is so flat, the cost of a highway is always proportional to its length. Thus, the least expensive highway system will be the one that minimizes the total highways length.

Input

The input consists of two parts. The first part describes all towns in the country, and the second part describes all of the highways that have already been built.

The first line of the input file contains a single integer N (1 <= N <= 750), representing the number of towns. The next N lines each contain two integers, xi and yi separated by a space. These values give the coordinates of ith town (for i from 1 to N). Coordinates will have an absolute value no greater than 10000. Every town has a unique location.

The next line contains a single integer M (0 <= M <= 1000), representing the number of existing highways. The next M lines each contain a pair of integers separated by a space. These two integers give a pair of town numbers which are already connected by a highway. Each pair of towns is connected by at most one highway. 

Output

Write to the output a single line for each new highway that should be built in order to connect all towns with minimal possible total length of new highways. Each highway should be presented by printing town numbers that this highway connects, separated by a space. 

If no new highways need to be built (all towns are already connected), then the output file should be created but it should be empty.

Sample Input

9
1 5
0 0 
3 2
4 5
5 1
0 4
5 2
1 2
5 3
3
1 3
9 7
1 2

Sample Output

1 6
3 7
4 9
5 7
8 3

//题意:输入分为两个部分第一部分让你输入的村庄的数量以及每个村庄的坐标,第二部分让你输入已经存在的道路的数量和每条道路连接的两个村庄。其实就是求最小生成树,有两种方法prim和Kruskal,Prim算法和kruskal算法用在不同时候时间不同,前者适合稠密图(点多的图),后者适合稀疏图(边多的图)如果题目数据比较大无法存邻接矩阵的形式,只能用后者,不然爆栈.、

这题我用的是prim

AC代码:

#include<stdio.h>
#define MAX 752
#define inf 0xfffffff  //最小值初始化一个很大的不可能的数
int dx[MAX],dy[MAX];  //用来存放每个村庄的坐标
double map[MAX][MAX];   //放邻接矩阵
int vis[MAX];      //vis[i]=1表示这个点已经被选入最小生成树
int n,m;
void prim(){
	int min,i,j,k;
	int adjvew[MAX];
	double lowcost[MAX];   //lowcost数组存放最小的权,每次循环都更新

	
	vis[1]=1;          //从第一个点开始遍历
	for(i=1;i<=n;i++)   //将与第一个点相连的全部点的权值遍历,存入lowcost数组。
	{
		lowcost[i]=map[1][i];
		adjvew[i]=1;   //adjvew存放的就是每个lowcost是哪个点散发出的初始化adjvew数组
	}
	for(i=1;i<=n;i++)      //循环完每一个点
	{
		min=inf;         //初始化最小值
		k=1;             //k用来存新加的点是第几个
		for(j=1;j<=n;j++)
		{
			if(!vis[j]&&min>lowcost[j]) //只有这个点没有进树而且lowcost比min小,选出最小的
			{
				min=lowcost[j];
				k=j;         //k存放这个最小的点
			}
		}
		vis[k]=1;         //表明k这个点已经加入到最小生成树中
		
		if(map[adjvew[k]][k]!=0)  //如何这个点的权不为0就输出这个边连接的两个点
		printf("%d %d\n",k,adjvew[k]);
	
		for(j=1;j<=n;j++)      //从刚选出的这个点继续往下循环完所有的点,更新lowcost数组
		{
			if(vis[j]==0&&lowcost[j]>map[k][j])
			{
				lowcost[j]=map[k][j];
				adjvew[j]=k;    //adjvew存放的就是每个lowcost是哪个点散发出的
			}
		}
		 
	}
	
}
int main()
{
	int i,j,x,y;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d%d",&dx[i],&dy[i]);
		 for(j=1;j<=i;j++)
		 {
		 	map[i][j]=map[j][i]=(dx[i]-dx[j])*(dx[i]-dx[j])+(dy[i]-dy[j])*(dy[i]-dy[j]);
		 	                        //这里没开方为了使简单
			 }	
	}
	scanf("%d",&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		map[x][y]=map[y][x]=0; //已经存在的道路 邻接矩阵上体现为0;
	}
	prim(); 	
/*for(i=1;i<=n;i++)       //为了输出邻接矩阵方便检查
{

for(j=1;j<=n;j++)
{

 printf("%d ",map[i][j]);
}
printf("\n");
}     */
	return 0;
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值