Highways POJ - 1751(最小生成树)详解注释

题目链接
Flatopia岛国完全平坦。不幸的是,Flatopia的公共高速公路系统非常糟糕。弗拉托利亚政府意识到了这个问题,并且已经建造了一些连接一些最重要城镇的高速公路。但是,仍有一些城镇无法通过高速公路抵达。有必要建造更多的高速公路,以便能够在不离开高速公路系统的情况下在任何一对城镇之间行驶。
Flatopian城镇的编号从1到N,城镇i的位置由笛卡尔坐标(xi,yi)给出。每条高速公路连接两个城镇。所有高速公路(原始高速公路和要建造的高速公路)都遵循直线,因此它们的长度等于城镇之间的笛卡尔距离。所有高速公路都可以在两个方向上使用。高速公路可以自由地相互交叉,但司机只能在位于两条高速公路尽头的小镇的高速公路之间切换。
Flatopian政府希望最大限度地降低建设新高速公路的成本。但是,他们希望保证每个城镇都可以从其他城镇到达公路。由于Flatopia是如此平坦,高速公路的成本总是与其长度成正比。因此,最便宜的高速公路系统将是最小化总公路长度的系统。
Sample Input
9
1 5
0 0
3 2
4 5
5 1
0 4
5 2
1 2
5 3
3
1 3
9 7
1 2
Sample Output
1 6
3 7
4 9
5 7
8 3

题意思路:N个点,给你N个点的坐标,现在还有Q条边已经连接好了。问把N个点怎么连接起来的花费的距离最短?
坑点:注意多组输入输出可能会超时。本题为:Special judgeYes,只要是符合要求的正确答案即可。prim或者kruskal的路径输出。
①prim,已经建好的边的权值设置为0。开一个pre数组//pre[i]记录距离i最近的点。那么建立的边也就为pre[i]和i,但是i节点不能是之前已经建立好的边,也就是dis[i]不能为0。
②kruskal,在输入的建好的边时候就把这两条边合并,然后统计建好了多少条边,还需要建立多少条边。
比如有4个点1,2,3,4,已经建好边有3条
1 2
2 1
3 1
此时还需要建立一条边,而不是还需要建立4 - 1 - 3 = 0条边 。

一:prim解法:

/*prim算法:已经建好的边的权值设置为0。开一个pre数组//pre[i]记录距离i最近的点。
那么建立的边也就为pre[i]和i,但是i节点不能是之前已经建立好的边,也就是dis[i]不能为0。*/
//本题就比普通的prim的算法多开了一个pre数组
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
const int maxn = 755;
const int inf = 0x3f3f3f3f;
int n, m, mp[maxn][maxn];
struct Point
{
    int x, y;
}point[maxn];
void prim()
{
    bool vis[maxn];
    int dis[maxn], pre[maxn];//pre[i]记录距离i最近的点
    //memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; i++)
    {
        dis[i] = mp[1][i];
        vis[i] = false;//此行与21行memset数组的效果一样
        pre[i] = 1;//pre数组一开始存储的全是1
    }
    //vis[1] = true; //此行注释掉会错,
    //for (int i = 1; i < n; i++)//因为:此行是n-1次循环,若要注释掉vis[1] = true; 则循环要改为for (int i = 1; i <= n; i++)
    for (int i = 1; i <= n; i++)
    {
        int mi = inf, v;
        for (int j = 1; j <= n; j++)
        {
            if (!vis[j] && dis[j] < mi)
            {
                mi = dis[j]; 
                v = j;
            }
        }
        if(dis[v] != 0) printf("%d %d\n",pre[v], v);//不是已经建好的路就输出当前建立的边
        vis[v] = true;
        for (int j = 1; j <= n; j++)
        {
            if (!vis[j] && dis[j] > mp[v][j])
            {
                dis[j] = mp[v][j];
                pre[j] = v;
            }
        }
    }
}
int main()
{
    scanf("%d", &n);//多组会wa
    {
        for (int i = 1; i <= n; i++)//从1到n依次加入点
        {
            scanf("%d%d", &point[i].x, &point[i].y);
            mp[i][i] = 0;//自己到自己的距离初始化为0
            for (int j = 1; j < i; j++)//新加入的点到所有已加入的点的距离存入mp
            {
                mp[i][j] = mp[j][i] = (point[i].x - point[j].x) * (point[i].x - point[j].x) +
                                    (point[i].y - point[j].y) * (point[i].y - point[j].y);
            }
        }
        int Q;
        scanf("%d", &Q);//Q条路已经被修建
        while (Q--)
        {
            int a, b;
            scanf("%d%d", &a, &b);//点a到点b的路已经存在,
            mp[a][b] = mp[b][a] = 0;//不用修建,存为0
        }
        prim();
    }
    return 0;
}

prim解法的跑代码过程以及图解
二:krusal解法:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
const int maxn = 755;
const int INF = 0x3f3f3f3f;
int n, m, cnt, f[maxn];
struct Point
{
    int x, y;
}point[maxn];
struct Edge
{
    int u, v, w;
    bool operator < (const Edge &A) const//重载<操作符。可以对两个Edge类型数据使用 < 操作符进行比较
    //括号中的const表示参数A对象不会被修改,最后的const表明调用函数对象不会被修改!
    {
        return w < A.w;
    }
}edge[maxn * maxn];
int Find(int x)//查找(x)根节点
{
    //return f[x] == x ? x : f[x] = Find(f[x]);//与26 27 28行代码功能一样
    int r=x;   //委托 r 去找(根节点)
    while(f[r]!=r)   //如果r的上级(父节点)不是r自己(也就是说找到的不是根节点)
        r=f[r];// r 就接着找他的上级,直到找到根节点为止。
    return r; //(返回根节点)
}
bool Union(int a, int b)//我想让虚竹和周芷若做朋友//    //判断a b是否连通
{ //如果已经连通,就不用管了 如果不连通,就把它们所在的连通分支合并起,
    int root1 = Find(a), root2 = Find(b);//虚竹的老大是玄慈,芷若MM的老大是灭绝
    if (root1 != root2) //玄慈和灭绝显然不是同一个人
    {
        f[root1] = root2;   //方丈只好委委屈屈地当了师太的手下啦
        return true;
    }
    return false;
}
void kruskal()
{
    for (int i = 0; i < m; i++)
    {
        int u = edge[i].u, v = edge[i].v, w = edge[i].w;
        if (Union(u, v)==true)
        {
            printf("%d %d\n", u, v);
            cnt++;
            if (cnt == n -1 ) break;
        }
    }
}
int main()
{
    scanf("%d", &n);//多组会wa
    {
        m = 0;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d%d", &point[i].x, &point[i].y);
            for (int j = 1; j < i; j++)
            {
                edge[m].u = i;
                edge[m].v = j;
                edge[m++].w = (point[i].x - point[j].x) * (point[i].x - point[j].x) +
                              (point[i].y - point[j].y) * (point[i].y - point[j].y);
            }
        }
        cnt = 0;//建好了0条边
        for (int i = 0; i <= n; i++)
            f[i] = i;//并查集初始化
        sort(edge, edge + m);//排序
        int Q;
        scanf("%d", &Q);
        while (Q--)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            if(Union(a, b)==true) cnt++;
        }
        kruskal();
    }
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sklearn中自带了波士顿房价数据集,可以通过以下代码导入: ``` from sklearn.datasets import load_boston boston = load_boston() X = boston.data # 特征矩阵 y = boston.target # 目标向量 ``` 其中,X是一个13维的特征矩阵,y是一个样本数量为506的目标向量。可以通过以下代码查看数据集的描述: ``` print(boston.DESCR) ``` 输出结果如下: ``` .. _boston_dataset: Boston house prices dataset --------------------------- **Data Set Characteristics:** :Number of Instances: 506 :Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target. :Attribute Information (in order): - CRIM per capita crime rate by town - ZN proportion of residential land zoned for lots over 25,000 sq.ft. - INDUS proportion of non-retail business acres per town - CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise) - NOX nitric oxides concentration (parts per 10 million) - RM average number of rooms per dwelling - AGE proportion of owner-occupied units built prior to 1940 - DIS weighted distances to five Boston employment centres - RAD index of accessibility to radial highways - TAX full-value property-tax rate per $10,000 - PTRATIO pupil-teacher ratio by town - B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town - LSTAT % lower status of the population - MEDV Median value of owner-occupied homes in $1000's :Missing Attribute Values: None :Creator: Harrison, D. and Rubinfeld, D.L. This is a copy of UCI ML housing dataset. https://archive.ics.uci.edu/ml/machine-learning-databases/housing/ This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University. The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonic prices and the demand for clean air', J. Environ. Economics & Management, vol.5, 81-102, 1978. Used in Belsley, Kuh & Welsch, 'Regression diagnostics ...', Wiley, 1980. N.B. Various transformations are used in the table on pages 244-261 of the latter. The Boston house-price data has been used in many machine learning papers that address regression problems. **References** - Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and Sources of Collinearity', Wiley, 1980. 244-261. - Quinlan,R. (1993). Combining Instance-Based and Model-Based Learning. In Proceedings on the Tenth International Conference of Machine Learning, 236-243, University of Massachusetts, Amherst. Morgan Kaufmann.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值