您的位置:首页 > 其它

uva 10397 Connect the Campus kruskal || prim

2015-08-21 21:42 369 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: