题解:
经分析(2)条件是不存在的,所以是一个最小生成树的模板题,然而用Kruskal需要存边。
n < 5000 所以 m < 5000*2500*3 会MLE,并且时间复杂度是O(E(logV)) 会TLE
于是用Prime,prime可以实时更新边,所以不会MLE,prime有两种写法,基于优先队列实现的时间复杂度是O(E(logV)),也可能会TLE,于是采用另一种O(V^2)的写法。
一个注意的地方求距离的时候用int存坐标会爆int,需要加(double) 强制转换
AC Code
Prime O(V^2)
#include <bits/stdc++.h>
using namespace std;
const double INF = 1e18;
const int maxn = 5000 + 10;
const int maxm = 2500;
int n;
int x[maxn];
int y[maxn];
double dist(int i, int j)
{
return sqrt((double)(x[i]-x[j])*(x[i]-x[j]) + (double)(y[i]-y[j])*(y[i]-y[j]));
}
bool vis[maxn];
double minc[maxn];
double prime()
{
for(int i = 0; i < n; i++) minc[i] = INF;
memset(vis,false,sizeof(vis));
minc[0] = 0;
double res = 0;
while(true)
{
int v = -1;
for(int u = 0; u < n; u++)
if(!vis[u] && (v == -1 || minc[u] < minc[v])) v = u;
if(v == -1) break;
vis[v] = true;
res += minc[v];
for(int u = 0; u < n; u++)
minc[u] = min(minc[u],dist(v,u));
}
return res;
}
int main()
{
scanf("%d",&n);
for(int i = 0; i < n; i++)
scanf("%d%d",&x[i],&y[i]);
double ans = prime();
printf("%.2lf\n",ans);
return 0;
}
TLE Code
Prime O(E(logV)) 基于优先队列实现
#include <bits/stdc++.h>
using namespace std;
typedef pair<double,int> P;
const double INF = 1e18;
const int maxn = 5000 + 10;
const int maxm = 2500;
int n;
int x[maxn];
int y[maxn];
double dist(int i, int j)
{
return sqrt((double)(x[i]-x[j])*(x[i]-x[j]) + (double)(y[i]-y[j])*(y[i]-y[j]));
}
bool vis[maxn];
double prime()
{
int tot = 0;
memset(vis,false,sizeof(vis));
double s = 0;
priority_queue <P, vector<P>, greater<P> > Q;
Q.push(P(0,0));
while(!Q.empty())
{
P p = Q.top();
Q.pop();
int u = p.second;
if(vis[u]) continue;
tot++;
vis[u] = true;
s += p.first;
if(tot == n) break;
for(int i = 0; i < n; i++)
{
if(!vis[i])
Q.push(P(dist(u,i),i));
}
}
return s;
}
int main()
{
scanf("%d",&n);
for(int i = 0; i < n; i++)
scanf("%d%d",&x[i],&y[i]);
double ans = prime();
printf("%.2lf\n",ans);
return 0;
}
TLE & MLECode
Kruskal O(E(logV))
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 5000 + 10;
const int maxm = 1000000 + 10;
int x[maxn];
int y[maxn];
int f[maxn];
struct edge{
int u,v;
double cost;
edge (int u = 0, int v = 0, double cost = 0) : u(u), v(v), cost(cost) {}
}es[maxm];
bool cmp(edge &a, edge &b)
{
return a.cost < b.cost;
}
void init()
{
for(int i = 0; i <= maxn; i++)
f[i] = i;
}
int find(int x)
{
return x == f[x]? x : f[x] = find(f[x]);
}
bool same(int x, int y)
{
return find(x) == find(y);
}
void unit(int x, int y)
{
x = find(x);
y = find(y);
f[x] = y;
}
int main()
{
int p;
int m = 0;
init();
scanf("%d",&p);
for(int i = 0; i < p; i++)
{
scanf("%d%d",&x[i],&y[i]);
}
for(int i = 0; i < p; i++)
for(int j = i+1 ; j < p; j++)
{
double cost = sqrt((double)(x[i]-x[j])*(x[i]-x[j]) + (double)(y[i]-y[j])*(y[i]-y[j]));
es[m++] = edge(i,j,cost);
}
sort(es,es+m,cmp);
double ans = 0;
int tot = 0;
for(int i = 0; i < m; i++)
{
edge e = es[i];
if(!same(e.u,e.v))
{
unit(e.u,e.v);
tot ++;
ans += e.cost;
if(tot == p - 1)
break;
}
}
printf("%.2lf\n",ans);
return 0;
}