uva 10397 Connect the Campus kruskal || prim

uva上的题目总是要难一些的。。。总是会拐弯抹角,这道题目给出有的建筑之间已经建好了光缆,让求最小生成树,我还是比较喜欢用kruskal算法,但是这道题目肯定用prim比较快,prim复杂度是n^2,kruskal复杂度eloge。

用kruskal时需要预先用并查集处理一下已经建好的光缆,让他们属于同一个祖先;

用prim算法的时候需要把他们的边置为0,这样算sum的时候就不会加上了。

代码:(kruskal)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<algorithm>
#define MAX 0x7fffffff

using namespace std;
struct node
{
	int i,j;
	double len;
}gra[640000];
int p[800],n;
int cmp(const void *a,const void *b)
{
	return ((node *)a)->len - ((node *)b)->len >0? 1 :-1;
}
int find(int x)
{
	if(x == p[x])
		return x;
	else
		return p[x] = find(p[x]);
}
int a[800],b[800];
double dist(int a,int b,int c,int d)
{
	return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
void kruskal()
{
	int i;
	double sum = 0;
	for(i=1; i<=n*(n-1)/2; i++)
	{
		int x = find(gra[i].i);
		int y = find(gra[i].j);
		if(x != y)
		{
			sum += gra[i].len;
			p[x] = y;
		}
	}
	//cout << sum << endl;
	printf("%.2lf\n",sum);
}
int main()
{
	int i,j,m,x,y;
	while(cin >> n)
	{
		int k = 1;
		for(i=1; i<=n; i++)
			cin >> a[i] >> b[i];
		for(i=1; i<=n-1; i++)
			for(j=i+1; j<=n; j++)
				{
					gra[k].i = i;
					gra[k].j = j;
					gra[k].len = dist(a[i],b[i],a[j],b[j]);
					k ++;
				}
		cin >> m;
		for(i=1; i<=n; i++)
			p[i] = i;
		for(i=1; i<=m; i++)
		{
			cin >> x >> y;
			int xx = find(x);
			int yy = find(y);
			if(xx != yy)
				p[xx] = yy;
		}
		qsort(gra+1,k-1,sizeof(gra[0]),cmp);
		kruskal();
	}
	return 0;
}

代码(prim):

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<algorithm>
#define MAX 0x7fffffff

using namespace std;
double gra[800][800];
int m,n;
int visit[800];
double d[800];
int xx ;
double dist(int a,int b,int c,int d)
{
	return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
void prim()
{
	int i,j,now;
	double sum = 0;
	double MIN;
	xx = 1;
	d[xx] = 0; visit[xx] = 1; now = xx;
	for(i=2; i<=n; i++)
	{
		for(j=1; j<=n; j++)
			if(!visit[j] && d[j] > gra[now][j])
				d[j] = gra[now][j];
		MIN = MAX;
		for(j=1; j<=n; j++)
			if(!visit[j] && MIN > d[j])
				MIN = d[now = j];
		visit[now] = 1;
		//printf("now = %d\n",now);
		//cout << MIN << endl;
		sum += MIN;
	}
	printf("%.2lf\n",sum);
}
int main()
{
	int i,j;
	int a[800],b[800];
	while(cin >> n)
	{
		for(i=1; i<=n; i++)
			cin >> a[i] >> b[i];
		for(i=1; i<=n-1; i++)
			for(j=i+1; j<=n; j++)
				gra[i][j] = gra[j][i] = dist(a[i],b[i],a[j],b[j]);
		cin >> m;
		memset(visit,0,sizeof(visit));
		for(i=1; i<=n; i++)
			d[i] = MAX;
		int x,y;
		for(i=1; i<=m; i++)
		{
			cin >> x >> y;
			gra[x][y] = gra[y][x] = 0;
		}
		prim();
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 09:54:04

uva 10397 Connect the Campus kruskal || prim的相关文章

uva 10397 Connect the Campus kruskal 算法变形

#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <vector> #include <cstri

uva 10397 - Connect the Campus

Problem E Connect the Campus Input: standard input Output: standard output Time Limit: 2 seconds Many new buildings are under construction on the campus of the University of Waterloo. The university has hired bricklayers, electricians, plumbers, and

uvaoj 10397 - Connect the Campus【最小生成树】

uvaoj 10397 - Connect the Campus Many new buildings are under construction on the campus of the University of Waterloo. The university has hired bricklayers, electricians, plumbers, and a computer programmer. A computer programmer? Yes, you have been

UVA10397 - Connect the Campus(最小生成树+并查集)

UVA10397 - Connect the Campus(最小生成树) 题目链接 题目大意:给你n个点,然后再给你m个已经连接的边,问如何使得所有的点都相连并且新建的边长度之和最小. 解题思路:最小生成树,但是有m条边是已经建好的,就将这些边的权值变成0,然后用kruskal的方法来求长度. 代码: #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> usin

ACM:最小生成树,kruskal &amp;&amp; prim,并查集

题目: 输入顶点数目,边的数目,输入每条边的两个顶点编号还有每条边的权值,求最小生成树,输出最小生成树的权值.. 注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图. kruskal----归并边:prim----归并点 方法一:kruskal,克鲁斯卡尔,并查集实现. #include <iostream> #include <algorithm> using name

Connect the Campus (Uva 10397 Prim || Kruskal + 并查集)

题意:给出n个点的坐标,要把n个点连通,使得总距离最小,可是有m对点已经连接,输入m,和m组a和b,表示a和b两点已经连接. 思路:两种做法.(1)用prim算法时,输入a,b.令mp[a][b]=0.然后进行一遍prim(2)Kruskal算法+并查集 代码: //prim写法 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <

Connect the Cities(MST prim)

Connect the Cities Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3371 Description In 2100, since the sea level rise, most of the cities disappear. Though some survived cities are still connect

Connect the Cities(prim)用prim都可能超时,交了20几发卡时过的

Connect the Cities Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 701 Accepted Submission(s): 212   Problem Description In 2100, since the sea level rise, most of the cities disappear. Though som

几个小模板:topology, dijkstra, spfa, floyd, kruskal, prim

1.topology: 1 #include <fstream> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstdio> 5 #include <cstring> 6 #include <cmath> 7 #include <cstdlib> 8 9 using namespace std; 10 11 #define EPS 1e-6 12 #de