当前位置:编程学习 > C/C++ >>

poj-1287 不是题目水,而是数据弱

这个题目很简单,就是最简单的最小生成树,并且用克鲁斯卡尔算法很容易。
但是,题目中说的边可能是无限的(The number of possible routes is unlimited),如果边有很多,该如何办呢?
 
当然,这里直接开10000条以上就行了,因为测试用例有限,加入10^10条呢?
这里说了最多50个点,那么最多也就1225条边,再多就是重复的,实际上我们只需要开这么大的空间就行,然后读入所有的边,将重复的保存最小值就可以了。
不过这里没必要,因为,边数比较少。。。。
 
直接代码,要想懂得此题目,首先要看看数据结构-并查集,不过本题目用普利姆算法可能更快点,因为点少,o(n^2).
 
[cpp] 
#include <cstdio> 
#include <iostream> 
#include <algorithm> 
using namespace std; 
 
#define nMaxEdgeNum 15000   //最大边数 
#define nMaxPointNum 100    //最多点数 
 
int father[nMaxPointNum];   //并查集模拟树的数组 
int rank[nMaxPointNum];     // 
 
typedef struct EDGE 

    int u, v, w; 
}Edge; 
Edge edge[nMaxEdgeNum]; 
 
int p, r, sum; 
 
//比较函数 
bool cmp(Edge a, Edge b) 

    return a.w < b.w; 

 
//下面依次是并查集的三个函数 
//初始化 
void Init(int n) 

    for (int i = 1; i <= n; ++ i) 
    { 
        father[i] = i; 
        rank[i] = 0; 
    } 

 
//查找 
int Find(int x) 

    if (x != father[x]) 
    { 
        father[x] = Find(father[x]); 
    } 
    return father[x]; 

 
//合并 
void Union(int x, int y) 

    int xx = Find(x); 
    int yy = Find(y); 
    if (rank[xx] > rank[yy]) 
    { 
        father[yy] = xx; 
    } 
    else   www.zzzyk.com
    { 
        father[xx] = yy; 
        if (rank[xx] == rank[yy]) 
        { 
            rank[yy] ++; 
        } 
    } 

 
//克鲁斯卡尔算法实现 
void Kruskal() 

    sum = 0; 
    Init(p); 
    sort(edge + 1, edge + r + 1, cmp); 
    for (int i = 1; i <= r; ++ i) 
    { 
        if (Find(edge[i].u) != Find(edge[i].v)) 
        { 
            sum += edge[i].w; 
            Union(edge[i].u, edge[i].v); 
        } 
    } 
    printf("%d\n",sum); 

 
int main() 

    while (scanf("%d", &p) && p) 
    { 
        scanf("%d", &r); 
        for (int i = 1; i <= r; ++ i) 
        { 
            scanf("%d %d %d",&edge[i].u, &edge[i].v, &edge[i].w); 
        } 
        Kruskal(); 
    } 
 
    return 0; 

作者:zhang20072844
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,