暑假集训专题练习记录——最小生成树 最短路

题目列表

A Jungle Roads(POJ1251)

最小生成树板子题,直接套板子就能过。

AC代码

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
const int max_n = 1e5;
int parent[max_n];
int myRank[max_n];

void init(int n)
{
   
    for (int i = 0; i < n; i++)
    {
   
        parent[i] = i;
        myRank[i] = 0;
    }
}

int find(int x)
{
   
    if (x != parent[x])
        parent[x] = find(parent[x]);
    return parent[x];
}

void unite(int x, int y)
{
   
    x = find(x);
    y = find(y);
    if (x == y)
        return;

    if (myRank[x] < myRank[y])
    {
   
        parent[x] = y;
    }
    else
    {
   
        parent[y] = x;
        if (myRank[x] == myRank[y])
        {
   
            myRank[x]++;
        }
    }
}

bool same(int x, int y)
{
   
    return find(x) == find(y);
}

struct edge
{
   
    int stN, edN, cost;
    bool operator<(edge e1)
    {
   
        return this->cost < e1.cost;
    }
} edges[max_n];

int krukal(int v, int e)
{
   
    sort(edges, edges + e);
    init(v);
    int res = 0;
    int nedge = 0;
    for (int i = 0; i < e && nedge != v - 1; i++)
    {
   
        edge et = edges[i];
        if (!same(et.stN, et.edN))
        {
   
            unite(et.stN, et.edN);
            res += et.cost;
            nedge++;
        }
    }
    if (nedge < v - 1)
        res = -1;
    return res;
}

int main()
{
   
    int n, index;
    while (cin >> n)
    {
   
        if (n == 0)
            break;
        cin >> index;

        for (int i = 0; i < index; i++)
            cin >> edges[i].stN >> edges[i].edN >> edges[i].cost;

        int ans = krukal(n, index);
        cout << ans << endl;
    }
    return 0;
}

B Networking(POJ1287)

还是板子题,没有什么需要注意的地方。

AC代码

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
const int max_n = 1e5;
int parent[max_n];

void init(int n)
{
   
    for (int i = 0; i < n + 10; i++)
        parent[i] = i;
}

int find(int x)
{
   
    if (x != parent[x])
        parent[x] = find(parent[x]);
    return parent[x];
}

void unite(int x, int y)
{
   
    x = find(x);
    y = find(y);
    if (x == y)
        return;

    parent[x] = y;
}

bool same(int x, int y)
{
   
    return find(x) == find(y);
}

struct edge
{
   
    int stN, edN, cost;
    bool operator<(edge e1)
    {
   
        return this->cost < e1.cost;
    }
} edges[max_n];

int krukal(int v, int e)
{
   
    sort(edges, edges + e);
    init(v);
    int res = 0;
    int nedge = 0;
    for (int i = 0; i < e && nedge != v - 1; i++)
    {
   
        edge et = edges[i];
        if (!same(et.stN, et.edN))
        {
   
            unite(et.stN, et.edN);
            res += et.cost;
            nedge++;
        }
    }

    if (nedge < v - 1) //不连通
        res = -1;
    return res;
}

int main()
{
   
    //点数 边数
    int n, index;
    while (cin >> n)
    {
   
        if (n == 0)
            break;
        cin >> index;

        for (int i = 0; i < index; i++)
            cin >> edges[i].stN >> edges[i].edN >> edges[i].cost;

        int ans = krukal(n, index);
        cout << ans << endl;
    }
    return 0;
}

C Building a Space Station(POJ2031)

题目大意:
求对立体中求得最小生成树。
思路:
先处理出来边,两个球如果相交了那么代表这条边得权值为0。然后求所有边得最小生成树就行了。

AC代码

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;
const int max_n = 1e4;

struct pp
{
   
    int index;
    double x, y, z, r;
};

double cost(pp p1, pp p2)
{
   
    double ans = sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y) + (p2.z - p1.z) * (p2.z - p1.z)) - (p1.r + p2.r);
    return ans > 0 ? ans : 0;
}

int parent[max_n];
vector<pp> vp;

struct edge
{
   
    int stN, edN;
    double co;
    bool operator<(edge e)
    {
   
        return co - e.co < 0;
    }
} edges[max_n];

void init(int n)
{
   
    for (int i = 0; i < n; i++)
        parent[i] = i;
}
int find(int x)
{
   
    if (x != parent[x])
        parent[x] = find(parent[x]);
    return parent[x];
}

void unit(int x, int y)
{
   
    x = find(x);
    y = find(y);
    if (x == y)
        return;
    parent[x] = y;
}
bool same(int x, int y)
{
   
    return find(x) == find(y);
}

int main()
{
   
    int n;
    while (cin >> n)
    {
   
        if (n == 0)
            break;

        vp.clear();

        for (int i = 0; i < n; i++)
        {
   
            pp tmp;
            cin >> tmp.x >> tmp.y >> tmp.z >> tmp.r;
            tmp.index = i;
            vp.push_back(tmp);
        }

        int index = 0;

        for (int i = 0; i < n - 1; i++)
        {
   
            for (int j = i + 1; j < n; j++)
            {
   
                edges[index].stN = vp[i].index;
                edges[index].edN = vp[j].index;
                edges[index].co = cost(vp[i], vp[j]);
                index++;
            }
        }

        init(n);

        sort(edges, edges + index);
        double res = 0;
        int nedge = 0;

        for (int i = 0; i < index && nedge != n - 1; i++)
        {
   
            edge e = edges[i];
            if (!same(e.stN, e.edN))
            {
   
                unit(e.stN, e.edN);
                res += e.co;
                nedge++;
            }
        }

        printf("%.3lf\n", res);
    }
    return 0;
}

D Constructing Roads(POJ2421)

题目大意:
给你一个邻接矩阵并且已知某些点已经连接好了,求最小生成树。
思路:
已经连好的点可以直接加入到并查集里面或者将 权值设为零。

AC代码

#include <iostream>
#include <algorithm>

using namespace std;
int arr[200][
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值