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