Description
Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.
Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1..N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Two space-separated integers: Xi and Yi
* Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.
Output
* Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.
Sample Input
4 1 1 1 3 1 2 3 4 3 1 4
Sample Output
4.00
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 1000+10
#define maxv 1000000+10
struct edge
{
int u,v;
double w;
friend bool operator < (edge a,edge b)
{
return a.w<b.w;
}
} e[maxv];
int pre[maxn];
int x[maxn],y[maxn];
int n,m,len;
void init()
{
for(int i=0; i<=n; i++)
pre[i]=i;
}
int Find(int c)
{
if(c==pre[c])
return c;
pre[c]=Find(pre[c]);
return pre[c];
}
int join(int cx,int cy)
{
int fx=Find(cx),fy=Find(cy);
if(fx!=fy)
{
pre[fy]=fx;
return 1;
}
return 0;
}
void Kruskal()
{
sort(e,e+len);
int cont=0;
double sum=0;
for(int i=0; i<len; i++)
{
if(join(e[i].u,e[i].v))
{
cont++;
sum+=e[i].w;
}
if(cont==n-1)
break;
}
printf("%.2f\n",sum);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
double w;
len=0;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&x[i],&y[i]);
for(int j=1; j<i; j++)
{
w=sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+1.0*(y[i]-y[j])*(y[i]-y[j]));
e[len].u=i,e[len].v=j,e[len++].w=w;
// e[len].u=j,e[len].v=i,e[len++].w=w;
}
}
int u,v;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&u,&v);
int fx=Find(u),fy=Find(v);
pre[fx]=fy;
}
Kruskal();
}
return 0;
}
ps:建双向边c++超时,g++AC,建单向边都AC,(其实只建单向边就好了,因为Kruskal只是按边的长度来排序的,不管你是从那个点到那个点)#include<stdio.h>
#include<math.h>
#include<string.h>
#define maxn 1000+10
#define min(a,b) (a<b?a:b)
const double inf=0x3f3f3f3f;
double e[maxn][maxn],d[maxn];
bool vis[maxn];
int x[maxn],y[maxn];
int n,m;
void Prim()
{
int i,j,v;
for(int i=1; i<=n; i++)
d[i]=e[1][i];
vis[1]=1;
double sum=0,minn;
while(1)
{
minn=inf;
for(i=1; i<=n; i++)
if(!vis[i]&&d[i]<minn)
minn=d[i],v=i;
if(minn==inf)
break;
vis[v]=true,sum+=minn;
for(i=1; i<=n; i++)
if(!vis[i]&&d[i]>e[v][i])
d[i]=e[v][i];
}
printf("%.2lf\n",sum);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
e[i][j]=e[j][i]=(i==j?0:inf);
d[i]=inf,vis[i]=0;
}
double w;
for(int i=1; i<=n; i++)
{
scanf("%d%d",&x[i],&y[i]);
for(int j=1; j<i; j++)
{
w=sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+1.0*(y[i]-y[j])*(y[i]-y[j]));
e[i][j]=e[j][i]=w;
}
}
int u,v;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&u,&v);
e[u][v]=e[v][u]=0;
}
Prim();
}
return 0;
}
ps:做的时候忘记Prim算法的本质了,结果初始的时候我给建了一片森林,真是wrong的无厘头0.0,初始的时候只需要随便选一个点,接着逐步建立起一个最小生成树就好了