//闲着没事,于是找来图论的题做做,开始很放松的用并查集做题,连着2题的错误,让我看到了并查集的局限性,对稠密的连通图用它会超//时,看来还是需要总结一下的:

并查集应用倒很好理解,只是对于这种体型明显需要大量的次数运算,所以这是如果用并查集,很大可能就会超时了,而此时便可以考虑prim算法,或者dijkstra算法的微变型:

//并查集的超时代码如下:TLE代码:

#include<stdio.h>

#include<math.h>

#include<stdlib.h>

#include<string.h>

struct node

{

int x,y;

double dis;

};

node count[1005];

int flag[1200];

int xx[1005];

int yy[1005];

int cmp(const void *a,const void *b)

{

struct node *c=(struct node *)a;

struct node *d=(struct node *)b;

return c->dis>d->dis?1:-1;

}

int find(int i)

{

if(flag[i]!=i)

return flag[i]=find(flag[i]);

return i;

}

void Merge(int i,int j)

{

int x2,y2;

x2=find(i);

y2=find(j);

if(x2>y2)

flag[x2]=y2;

else

flag[y2]=x2;

}

int main()

{

int n,m,i,j,k1,k2,k;

double sum;

scanf("%d%d",&n,&m);

memset(flag,0,sizeof(flag));

memset(count,0,sizeof(count));

memset(xx,0,sizeof(xx));

memset(yy,0,sizeof(yy));

for(i=1;i<=n;i++)

flag[i]=i;

k=0;

for(i=0;i<n;i++)

{

scanf("%d%d",&xx[i],&yy[i]);

for(j=0;j<i;j++)

{

count[k].x=i+1;

count[k].y=j+1;

count[k].dis=sqrt((xx[i]-xx[j])*(xx[i]-xx[j])+(yy[i]-yy[j])*(yy[i]-yy[j]));

k++;

}

}

for(i=0;i<m;i++)

{

scanf("%d%d",&k1,&k2);

Merge(k1,k2);

}

qsort(count,k,sizeof(count[0]),cmp);

sum=0;

for(i=0;i<k;i++)

{

k1=find(count[i].x);

k2=find(count[i].y);

if(k1!=k2)

{

sum+=count[i].dis;

Merge(count[i].x,count[i].y);

}

}

printf("%.2f\n",sum);

return 0;

}

//换个做法,prm如下:AC代码:

#include<stdio.h>

#include<math.h>

#include<stdlib.h>

#include<string.h>

#define inf 0xffffffffff

struct node

{

double x,y;

};

node point[1002];

double map[1002][1002];

double count[1002];

int flag[1002];

__int64 n,m;

double get_dis(double x1,double y1,double x2,double y2)

{

return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

}

double prm()

{

int i,j,k;

double min,ans;

for(i=0;i<n;i++)

{

flag[i]=0;

count[i]=map[0][i];

}

flag[0]=1;

count[0]=0;

ans=0;

for(i=1;i<n;i++)

{

min=inf;

k=0;

for(j=0;j<n;j++)

{

if(flag[j]==0&&count[j]<min)

{

min=count[j];

k=j;

}

}

if(min==inf)

return -1;

ans=ans+min;

flag[k]=1;

for(j=0;j<n;j++)

 if(flag[j]==0&&count[j]>map[k][j])

 count[j]=map[k][j];

}

return ans;

}

int main()

{

int i,j,x,y;

double dis,ans;

    scanf("%I64d%I64d",&n,&m);

for(i=0;i<n;i++)

scanf("%lf%lf",&point[i].x,&point[i].y);

for(i=0;i<n;i++)

{

map[i][i]=0;

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

{

dis=get_dis(point[i].x,point[i].y,point[j].x,point[j].y);

map[i][j]=dis;

map[j][i]=dis;

}

}

for(i=0;i<m;i++)

{

scanf("%d%d",&x,&y);

map[x-1][y-1]=0;

map[y-1][x-1]=0;

}

ans=prm();

printf("%.2f\n",ans);

return 0;

}

posted on 2011-08-20 17:01  world_ding  阅读(253)  评论(0编辑  收藏  举报