Codeforces Round #508 (Div. 2) E. Maximum Matching(欧拉路径)
E. Maximum Matching
题目链接:https://codeforces.com/contest/1038/problem/E
题意:
给出n个项链,每条项链左边和右边都有一种颜色(范围1~4),然后每条项链都有对应的价值。
现在你可以任意改变项链的位置,也可以交换左右两边的颜色,问怎么做才能得到最大的价值。一条项链得到价值,就要求其左边的颜色和左边的项链右边颜色相等,并且右边的颜色和右边项链左边的颜色相等。
题解:
分析就可以发现这个题就是找一条权值最大的欧拉路径(每条边刚好经过一次),我们这样构造,将两边的颜色看作点,然后价值看作边上的权值并且连接这两个点。
由于存在欧拉路径的充要条件就是度数为奇数的点不超过两个,这个题目中最多只有四个点,所以我们只需要枚举去掉一条边然后来跑欧拉路径就是了。
具体细节见代码吧:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 105; int n, sum; int d[N], vis[N], del[N],check[N]; struct node { int id, v, val; }; vector <node> g[N], edges[N]; void Euler(int u, int fa) { check[u]=1; for(auto v : g[u]) { if(del[v.id] || vis[v.id]) continue ; vis[v.id]=1; sum += v.val; Euler(v.v, u); } } bool Can() { int cnt = 0; for(int i = 1; i <= 4; i++) { if(check[i] && (d[i] & 1)) cnt++; } return cnt <= 2; } void init(){ memset(vis, 0, sizeof(vis)); memset(check,0,sizeof(check)); sum = 0; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n; for(int i = 1; i <= n; i++) { int c1, c2, v; cin >> c1 >> v >> c2; g[c1].push_back(node{i, c2, v}); g[c2].push_back(node{i, c1, v}); d[c1]++; d[c2]++; edges[i].push_back(node{c1, c2, v}); } int ans = 0; for(int i = 1; i <= 4; i++) { init(); Euler(i, -1); if(Can()) ans = max(ans, sum); } for(int i = 1; i <= n; i++) { del[i - 1] = 0; del[i] = 1; d[edges[i][0].id]--; d[edges[i][0].v]--; for(int j = 1; j <= 4; j++) { init(); Euler(j, -1); if(Can()){ ans = max(ans, sum); } } d[edges[i][0].id]++; d[edges[i][0].v]++; } cout << ans; return 0; }
重要的是自信,一旦有了自信,人就会赢得一切。