SEERC 2019 J. Graph and Cycles

题意:给出一个有n(n为奇数)个点的无向完全图,可以从这张图中分割出任意个圈,任意两个分割出来的圈没有重叠的边,而且图中的每一条边必定属于其中一个圈。圈分割出来后,对于其中的每个顶点的两条边取最大值然后相加作为该圈的重量,问如何分割这张图能使所有圈的重量和最小。

原题链接:https://codeforces.ml/gym/102392/problem/J


 

这个题目给出了点数必为奇数的条件,但是赛中没对这个条件进行深入思考,结果在跑欧拉图的想法上一路走到黑,哎。
点数为奇数,意味着每个点的度数为偶数,那么就可以对一个点的所有边从小到大排序后,两两边顺着成一对作为圈的组成部分(具体是哪个圈不重要,知道确实是属于某个圈就行了),就这么个贪心,然后直接算即可。

#include <bits/stdc++.h>
#define rep(i, l, r) for(long long i=l; i<=r ;i++)
using namespace std;

typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
ll gcd(ll n, ll m) { return n % m == 0 ? m : gcd(m, n % m);}

const int Maxn = 1000 + 10;
struct Edge{
    ll v, w;
    Edge(ll v, ll w): v(v), w(w) {}
    bool operator < (const Edge& B) const{
        return w < B.w;
    }
};

vector<vector<Edge> > G(Maxn);

int main()
{
    ios::sync_with_stdio(false);
    //freopen("data.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int n;
    cin>>n;
    for(int i=0; i<n * (n-1) / 2 ;i++){
        ll u, v, w;
        cin>>u>>v>>w;
        G[u].push_back(Edge(v, w));
        G[v].push_back(Edge(u, w));
    }

    for(int i=1; i<=n ;i++)
        sort(G[i].begin(), G[i].end());
    
    ll ans = 0;
    for(int i=1; i<=n ;i++)
        for(int j=0; j<(n-1)/2 ;j++){
            ll w1 = G[i][2*j].w;
            ll w2 = G[i][2*j+1].w;
            ans += max(w1, w2);
        }

    cout<<ans;

    return 0;
}

 

posted @ 2020-04-13 23:27  雾里尘埃  阅读(360)  评论(0编辑  收藏  举报