最小生成树prime算法——洛谷P1265公路修建

洛谷P1625公路修建

题解:
经分析(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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值