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; }