当前位置:   article > 正文

Codeforces Round #770 (Div. 2) E. Fair Share(欧拉回路)_codeforces 欧拉回路

codeforces 欧拉回路

题目

m(1<=m<=1e5)个数组,第i个数组的长度为ni(2<=ni<=2e5,ni为偶数)

第i个数组内的第j个值aij(1<=aij<=1e9),sumni<=2e5

问是否能把这些整数分成两个multiset,不妨称为L集合和R集合,

使得每个数组内恰有一半元素在L集合内,另一半元素在R集合内,

且L集合和R集合最终是相同的multiset

思路来源

palayutm、wifiii代码

题解

如果想到欧拉回路的构造,就很好做了

首先考虑无解的情形,某一种数字出现了奇数次,一定无解;否则,一定有解

先把数字离散化,然后这里给出一种构图方式:

第i个数组中,ai0和ai1连无向边,ai2和ai3连无向边,以此类推

相当于ai0和ai1位于二分图的不同侧,ai2和ai3同理,

这也将导致,每个出现的值,都有一条无向边可连,即每出现一次,度数就加一

可以发现,对于图上每个点(离散化后的数字)来说,

由于出现次数是偶数,所以度数为偶数,所以欧拉回路一定有解

不妨在某一种欧拉回路的方案中,边x是从第i个数组的a值指向b值的,

给边定向,不妨给b值划分到R集合,给a值划分到L集合

无论同一个数组内的边如何定向,都恰有一半属于L,另一半属于R

而对于每个数字v来说,恰有一半边从v出发指向其他点,另一半边从其他点出发回到v

这里试了一下c11和c17的语法,感觉还挺好用的

心得

反向考虑,为什么这么建图,

由于每个数字出现是偶数,所以每个aij连一条边,就能保证欧拉回路有解

由于最后每个数组内恰有ni/2个位于L集合,另ni/2个位于R集合,

所以相当于有ni/2对互斥关系,就对应在每个数组内建ni/2对两两结对的边,

给边定向时,让相邻点位于不同集合,即可达到这个目的

这与官方题解中,二分图左侧点i表示第i个数组,右侧点j表示数字j的建图方法,本质一致

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. void fast(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
  4. int main(){
  5. fast();
  6. int m,n;
  7. cin>>m;
  8. vector<vector<int> >a(m),ans(m);
  9. vector<int>b;
  10. for(int i=0;i<m;++i){
  11. cin>>n;
  12. a[i].resize(n);
  13. ans[i].resize(n);
  14. for(int j=0;j<n;++j){
  15. cin>>a[i][j];
  16. b.push_back(a[i][j]);
  17. }
  18. }
  19. sort(b.begin(),b.end());
  20. b.erase(unique(b.begin(),b.end()),b.end());
  21. vector<int>deg(b.size());
  22. for(int i=0;i<m;++i){
  23. for(auto &v:a[i]){
  24. v=lower_bound(b.begin(),b.end(),v)-b.begin();
  25. deg[v]++;
  26. }
  27. }
  28. for(auto &v:deg){
  29. if(v&1){
  30. cout<<"NO"<<endl;
  31. return 0;
  32. }
  33. }
  34. vector<vector<array<int,4>> >e(b.size());
  35. int id=0;
  36. for(int i=0;i<m;++i){
  37. for(int j=1;j<a[i].size();j+=2){
  38. e[a[i][j]].push_back({a[i][j-1],i,j,id});
  39. e[a[i][j-1]].push_back({a[i][j],i,j-1,id});
  40. id++;
  41. }
  42. }
  43. vector<bool>vis(id);
  44. function<void(int)> dfs = [&](int u){
  45. while(!e[u].empty()){
  46. auto [v,i,j,id]=e[u].back();
  47. e[u].pop_back();
  48. if(vis[id])continue;
  49. vis[id]=1;
  50. ans[i][j]=1;
  51. dfs(v);
  52. }
  53. };
  54. for(int i=0;i<b.size();++i){
  55. dfs(i);
  56. }
  57. cout<<"YES"<<endl;
  58. for(int i=0;i<m;++i){
  59. for(auto &v:ans[i]){
  60. cout<<(v?'L':'R');
  61. }
  62. cout<<endl;
  63. }
  64. return 0;
  65. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/1015940
推荐阅读
相关标签
  

闽ICP备14008679号