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;
}
用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;
}
相关文章推荐
- 淘宝吴雪军:自然语言处理技术在搜索和广告中的应用
- nyoj 1058 部分和问题
- js的History对象
- 继承,抽象,接口,多态
- JList的ListSelectionEvent的几个问题请教
- 关键字Static
- 五大常用算法之五:分支限界法
- Java反射性能优化(上)
- poj 2777 线段树难题
- 施一公在《科学》发表突破性成果 专家称有望拿诺奖
- poj 2513 Colored Sticks(欧拉路径+并检查集合+特里)
- Mysql 建表 数据类型选择
- NYOJ-458:小光棍数
- java.lang.UnsatisfiedLinkError: Couldn't load libjniFramework from loader
- 寻找数组中的最大值和最小值
- 五大常用算法之四:回溯法
- [C++11 并发编程] 08 - Mutex std::unique_lock
- HDU 1394 Minimum Inversion Number
- 黑马程序员----java基础之异常和File文件类
- 【待整理】IOS开发之下载