P2872 [USACO07DEC]Building Roads Skruskal

Posted jason66661010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2872 [USACO07DEC]Building Roads Skruskal相关的知识,希望对你有一定的参考价值。

题目

技术图片

 

 技术图片

 

 思路

开始的思路就是使用kruskal不停选择最短的边加入最小生成树,但是我发现这道题不但没有给路径,而且知识给了一部分已经修建的路径,那么如何判断我们的最小生成树用不用某一条已经修好的边呢?是算上已经修建好的边之后答案最小还是有另外更小的路径呢??咋判断呢?

问题一:没有路径:这道题人家给的是点的坐标,有了最表就可以求解距离,也就是说图中任何一点到任何一点的距离我们现在可以求了

问题二:如何判断已修建的用不用:既然使用了kruskal算法,就需要将所有的边都求出来再进行比较,这时候我们就可以判断,如果此时某条边在计算它的长度时发现是已经修建好的,就把它的长度设为0

最后使用算法寻找就行

缺点

这种方法需要在所有的边中寻找,其实就是在一个完全图中寻找,当边数较大的时候适合使用prim而不是kruskal,但是本题数据较小,所以可以过

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
#define maxm 1000001
#define maxn 1010
struct node
{
    int from;
    int to;
    double dis;
}e[maxm*2];//自己补的边
struct point
{
    double x;
    double y;

}list[maxn];//点集
bool cmp(struct node &a, struct node &b)
{
    return a.dis < b.dis;
}
int father[maxn];
int road[maxn][maxn];//记录已经修好的路
int n, m, cnt = 0;
double allcount = 0;//答案
int find(int x)
{
    if (father[x] == x)
        return x;
    return father[x] = find(father[x]);
}

int kruskal()
{
    sort(e, e + cnt, cmp);
    for (int i = 0; i < cnt; i++)
    {
        int tempx = find(e[i].from);
        int tempy = find(e[i].to);
        if (tempx == tempy)continue;
        allcount += e[i].dis;
        father[tempx] = tempy;
    }
    return allcount;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%lf%lf", &list[i].x, &list[i].y);
    for (int i = 1; i <= n; i++)father[i] = i;
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        scanf("%d%d",&a, &b);
        road[a][b] = road[b][a] = 1;
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)//这里只需要补一半的边 1 2 300 ; 2 1 300 对本题意义一样
        {
            if (i == j)continue;
            e[cnt].from = j; e[cnt].to = i;
            if(road[i][j]==0)e[cnt].dis = sqrt((list[i].x - list[j].x)*(list[i].x - list[j].x) + (list[i].y- list[j].y)*(list[i].y-list[j].y));
            else e[cnt].dis = 0;
            cnt++;
        }
    }
    kruskal();
    printf("%.2lf", allcount);
}

 

以上是关于P2872 [USACO07DEC]Building Roads Skruskal的主要内容,如果未能解决你的问题,请参考以下文章

P2872 [USACO07DEC]Building Roads S

洛谷 P2872 [USACO07DEC]Building Roads S

P2872 [USACO07DEC]Building Roads Skruskal

P2872 [USACO07DEC]Building Roads S(最小生成树)

[USACO07DEC]道路建设Building Roads

[USACO07DEC]Mud Puddles S