最小生成树 Problem B: Freckles

>>>>>>题目地址<<<<<<

妈的,在codeup提交就只有50分,去另一个TK题库提交就AC了,还白买了个数据

  • 思路1 Prim
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
double d[maxn];
bool vis[maxn];

struct node
{
    double x, y;
};
struct tmp_node
{
    int id;
    double d;
    bool operator < (const tmp_node & tmp) const { return d > tmp.d; }
};
double Dis(node a, node b)
{
    double lenx = abs(a.x - b.x), leny = abs(a.y - b.y);
    return sqrt(lenx * lenx + leny * leny);
}
double Prim(int start, int n, vector<node> & v)
{
    fill(d, d + n, DBL_MAX);
    memset(vis, false, sizeof(vis));
    d[start] = 0;
    priority_queue<tmp_node> pq;
    pq.push(tmp_node{start, 0});
    double ans = 0;
    while(!pq.empty())
    {
        tmp_node now = pq.top();
        pq.pop();
        if(vis[now.id]) continue;
        vis[now.id] = true;
        ans += d[now.id];
        for(int i = 0; i < n; ++i)
        {
            if(vis[i] == false)
            {
                double len = Dis(v[now.id], v[i]);
                if(len < d[i])
                {
                    d[i] = len;
                    pq.push(tmp_node{i, d[i]});
                }
            }
        }
    }
    return ans;
}

int main()
{
    int n;
    while(scanf("%d", &n) != EOF && n != 0)
    {
        vector<node> ans(n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%lf %lf", &ans[i].x, &ans[i].y);
        }
        printf("%.2f\n", Prim(0, n, ans));
    }
    return 0;
}

  • 思路 2 Kruskal
#include <bits/stdc++.h>
using namespace std;
struct Node
{
    double x, y;
}node[110];
struct edge
{
    int v1, v2;
    double len;
};
vector<edge> ans;
void Init(vector<int> & father) { for(int i = 0; i < father.size(); ++i) father[i] = i; }
int FindRoot(int x, vector<int> & father)
{
    int tmp = x;
    while(father[x] != x)
    {
        x = father[x];
    }
    while(father[tmp] != tmp)
    {
        int tmp2 = tmp;
        tmp = father[tmp];
        father[tmp2] = x;
    }
    return x;
}
double Dis(const Node & a, const Node & b)
{
    double lenx = a.x - b.x, leny = a.y - b.y;
    return sqrt(lenx * lenx + leny * leny);
}
bool cmp(const edge & a, const edge & b) { return a.len < b.len; }
double Kruskal(int nv, vector<edge> & v)
{
    vector<int> father(nv+1);	//注意这里并查集是用来查顶点的
    Init(father);
    sort(v.begin(), v.end(), cmp);
    double ans = 0;
    int numE = 0;
    for(int i = 0; i < v.size(); ++i)
    {
        int ra = FindRoot(v[i].v1, father), rb = FindRoot(v[i].v2, father);
        if(ra != rb)
        {
            father[ra] = rb;
            ans += v[i].len;
            numE++;
            if(numE >= nv-1) break;
        }
    }
    if(numE != nv-1) return -1;
    else return ans;
}
int main()
{
    int n;
    while(scanf("%d", &n) != EOF && n != 0)
    {
        for(int i = 0; i < n; ++i)
        {
            scanf("%lf %lf", &node[i].x, &node[i].y);
            for(int j = 0; j < i; ++j)
            {
                double len = Dis(node[j], node[i]);
                ans.push_back(edge{j, i, len});
            }
        }
        printf("%.2f\n", Kruskal(n, ans));
        ans.clear();
    }
    return 0;
}

  • 思路 3 Kruskal 堆优化
#include <bits/stdc++.h>
using namespace std;
struct Node
{
    double x, y;
}node[110];
struct edge
{
    int v1, v2;
    double len;
    bool operator < (const edge & tmp) const { return len > tmp.len; }
};
void Init(vector<int> & father) { for(int i = 0; i < father.size(); ++i) father[i] = i; }
int FindRoot(int x, vector<int> & father)
{
    int tmp = x;
    while(father[x] != x)
    {
        x = father[x];
    }
    while(father[tmp] != tmp)
    {
        int tmp2 = tmp;
        tmp = father[tmp];
        father[tmp2] = x;
    }
    return x;
}
double Dis(const Node & a, const Node & b)
{
    double lenx = a.x - b.x, leny = a.y - b.y;
    return sqrt(lenx * lenx + leny * leny);
}
double Kruskal(int nv, priority_queue<edge> & pq)
{
    vector<int> father(nv+1);
    Init(father);
    double ans = 0;
    int numE = 0;
    while(!pq.empty())
    {
        edge now = pq.top();
        pq.pop();
        int ra = FindRoot(now.v1, father), rb = FindRoot(now.v2, father);
        if(ra != rb)
        {
            father[ra] = rb;
            ans += now.len;
            numE++;
            if(numE >= nv-1) break;
        }
    }
    if(numE != nv-1) return -1;
    else return ans;
}
int main()
{
    int n;
    while(scanf("%d", &n) != EOF && n != 0)
    {
        priority_queue<edge> ans;
        for(int i = 0; i < n; ++i)
        {
            scanf("%lf %lf", &node[i].x, &node[i].y);
            for(int j = 0; j < i; ++j)
            {
                double len = Dis(node[j], node[i]);
                ans.push(edge{j, i, len});
            }
        }
        printf("%.2f\n", Kruskal(n, ans));

    }
    return 0;
}

发布了316 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42347617/article/details/104861485