CCF CSP 数据中心

题目

试题编号: 201812-4
试题名称: 数据中心
时间限制: 1.0s
内存限制: 512.0MB
问题描述:
在这里插入图片描述
在这里插入图片描述
样例输入
4
5
1
1 2 3
1 3 4
1 4 5
2 3 8
3 4 2
样例输出
4
样例说明
下图是样例说明。
在这里插入图片描述
在这里插入图片描述

分析

虽然题目说的很复杂,但是仔细观察样例后发现,其实就是一个最小生成树的问题,甚至都不需要考虑根节点在什么位置,因为无论在什么位置,只要把最小生成树求出来,问题就是符合题目要求的。

代码

代码1:写cmp函数,不使用容器

#include 
using namespace std;
#define MAX 100001
#define MAXN 500001
struct Edge{
    int u;
    int v;
    int w;
    Edge(){};
    Edge(int u1, int v1, int w1):u(u1), v(v1), w(w1){}
};
int pre[MAXN];
Edge edge[MAX];
bool cmp(Edge e1, Edge e2){
    return e1.w < e2.w;
}
int find(int root){
    int tmp, son;
    son = root;
    while(root != pre[root]){
        root = pre[root];
    }
    while(son != root){
        tmp = pre[son];
        pre[son] = root;
        son = root;
    }
    return root;
}
bool join(int x, int y){
    int rootx = find(x);
    int rooty = find(y);
    if(rootx != rooty){
        pre[rootx] = rooty;
        return true;
    }
    return false;
}
int main(){
    int n = 0, m = 0, root = 0, i = 0, ans = 0, num = 0;
    cin >> n >> m >> root;
    for(i=0; i<n; i++){
        pre[i] = i;
    }
    for(i=0; i<m; i++){
        cin >> edge[i].u >> edge[i].v >> edge[i].w;
    }
    sort(edge, edge+m, cmp);
    for(i=0; i<m; i++){
        if(join(edge[i].u, edge[i].v)){
            ans = edge[i].w;
            num += 1;
            if(num == n-1){
                break;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

代码2:重载 < 运算符,不使用容器

#include 
using namespace std;
#define MAX 100001
#define MAXN 500001
struct Edge{
    int u;
    int v;
    int w;
    Edge(){};
    Edge(int u1, int v1, int w1):u(u1), v(v1), w(w1){}
    bool operator < (struct Edge &e1){
        return this->w < e1.w;
    }
};
int pre[MAXN];
Edge edge[MAX];
int find(int root){
    int tmp, son;
    son = root;
    while(root != pre[root]){
        root = pre[root];
    }
    while(son != root){
        tmp = pre[son];
        pre[son] = root;
        son = root;
    }
    return root;
}
bool join(int x, int y){
    int rootx = find(x);
    int rooty = find(y);
    if(rootx != rooty){
        pre[rootx] = rooty;
        return true;
    }
    return false;
}
int main(){
    int n = 0, m = 0, root = 0, i = 0, ans = 0, num = 0;
    cin >> n >> m >> root;
    for(i=0; i<n; i++){
        pre[i] = i;
    }
    for(i=0; i<m; i++){
        cin >> edge[i].u >> edge[i].v >> edge[i].w;
    }
    sort(edge, edge+m, cmp);
    for(i=0; i<m; i++){
        if(join(edge[i].u, edge[i].v)){
            ans = edge[i].w;
            num += 1;
            if(num == n-1){
                break;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

代码3:重载 < 运算符,使用容器

#include 
using namespace std;
struct Edge{
    int u;
    int v;
    int w;
    Edge(){}
    Edge(int u1, int v1, int w1):u(u1), v(v1), w(w1){}
    bool operator < (struct Edge &e1){
        return this->w < e1.w;
    }
};
const int maxn = 500001;
const int maxm = 100001;
int pre[maxn];
vector<Edge> edge;
int findx(int root){
    int son, tmp;
    son = root;
    while(root != pre[root]){
        root  = pre[root];
    }
    while(son != root){
        tmp = pre[son];
        pre[son] = root;
        son = tmp;
    }
    return root;
}
int join(int root1, int root2){
    int x = findx(root1);
    int y = findx(root2);
    if(x != y){
        pre[x] = y;
        return true;
    }
    return false;
}
int main(){
    int n = 0, m = 0, i = 0, ans = 0, num = 0, root = 0;
    int tmp1, tmp2, tmp3;
    cin >> n >> m >> root;
    for(i=0; i<m; i++){
        cin >> tmp1 >> tmp2 >> tmp3;
        edge.push_back(Edge(tmp1, tmp2, tmp3));
    }
    for(i=0; i<n; i++){
        pre[i] = i;
    }
    sort(edge.begin(), edge.end());
    for(vector<Edge>::iterator it = edge.begin(); it != edge.end(); it++){
        if(join(it->u, it->v)){
            ans = it->w;
            num++;
            if(num == n-1){
                cout << ans;
                break;
            }
        }
    }
    return 0;
}