NOIP模拟 wall - 最大生成树

题目大意:

给出n个点,第i个点坐标是(\(x_i, y_i\)),给出m条边,第i条边的权值是\(w_i\),求将图变成一颗树所需要删除边的最小权值和。

题目分析:

首先要看出坐标其实是出题人使出的障眼法,把人往计算几何引。看透问题后就知道这是求一颗最大生成树。

code:

#include<bits/stdc++.h>
using namespace std;

const int N = 100005, M = 200005;
int n, m, T;
struct node{
    int a, b, c;
    inline bool operator < (const node &b) const{
        return c > b.c;
    }
};
vector<node> edges;
int anc[N];
typedef long long ll;
ll ans1, ans2;

inline int getAnc(int x){return x == anc[x] ? x : (anc[x] = getAnc(anc[x]));}

int main(){
    freopen("h.in", "r", stdin);
    ios::sync_with_stdio(false);
    cin.tie(NULL), cout.tie(NULL);
    cin >> T;
    while(T--){
        cin >> n >> m; 
        edges.clear(); ans1 = 0, ans2 = m;
        for(int i = 1; i <= n; i++) anc[i] = i;
        for(int i = 1; i <= n; i++){int x, y; cin >> x >> y;}
        for(int i = 1; i <= m; i++){
            int x, y, w; cin >> x >> y >> w;
            edges.push_back((node){x, y, w});
            ans1 += 1ll*w;
        }
        sort(edges.begin(), edges.end());
        for(int i = 0; i < edges.size(); i++){
            int f1 = getAnc(edges[i].a), f2 = getAnc(edges[i].b);
            if(f1 != f2){anc[f1] = f2, ans1 -= 1ll*edges[i].c, ans2--;}
        }
        cout << ans2 << " " << ans1 << endl;
    }
    return 0;
}
posted @ 2017-10-17 20:20  CzYoL  阅读(162)  评论(0编辑  收藏  举报