//闲着没事,于是找来图论的题做做,开始很放松的用并查集做题,连着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;
}