当前位置: 首页 > news >正文

赛前训练3 欧拉路

以下,斜体表示注意点,粗体表示技巧点。

无向图欧拉路径的判定:

  • 除去孤点之外图联通

  • 度数为奇数的点只有 \(0\)\(2\) 个。

有向图欧拉路径的判定:

  • 除去孤点之外图联通。

  • 出度比入度大一或入度比出度大一的有 \(0\)\(2\) 个。

  • 除了第二条中的点,全都是入度等于出度的点

A

拆边空间大小翻倍

将每条边拆成两条,然后跑有向图欧拉路径即可。

实现
#include<bits/stdc++.h>
#define int long long
using namespace std;const int N=1e4+5;
int n,m,cnt;
int ans[N*10];
vector<int> G[N];void dfs(int cur){for(int &i:G[cur]){if(i){int x=i; i=0;dfs(x);}}ans[++cnt]=cur;
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n>>m;for(int i=1,u,v;i<=m;i++){cin>>u>>v;G[u].push_back(v);G[v].push_back(u);}cnt=0,dfs(1);for(int i=cnt;i>=1;i--)cout<<ans[i]<<'\n';return 0;
}

B

判孤点

对于每个连通块,累加其贡献,即连通块中度数为奇数点的个数的一半,孤点和没有奇数点的情况不算。

实现
#include<bits/stdc++.h>
#define int long long
using namespace std;const int N=2e5+5;
int n,m,cnt,siz;
int d[N],dfn[N];
vector<int> G[N];void dfs(int cur){if(d[cur]&1)cnt++;dfn[cur]=1,siz++;for(int i:G[cur])if(!dfn[i])dfs(i);
}
void solve(){for(int i=1;i<=n;i++)G[i].clear(),d[i]=dfn[i]=0;for(int i=1,u,v;i<=m;i++){cin>>u>>v;G[u].push_back(v);G[v].push_back(u); d[u]++,d[v]++;}if(!m){cout<<"0\n";return;}int ans=0;for(int i=1;i<=n;i++){if(!dfn[i]){cnt=siz=0,dfs(i);if(siz>1)ans+=1+(cnt>2?(cnt-2)/2:0);}}cout<<ans<<'\n';
}signed main(){ios::sync_with_stdio(0);cin.tie(0);for(;cin>>n>>m;solve());return 0;
}

C

仍然考虑拆边,于是题目转化为边翻倍之后有多少种方案使得删掉两条边后仍具有欧拉回路。

删掉两条边理论上会增加四个奇数点,但可以删掉共点的边,这一部分贡献是 \(\sum \operatorname{C}^2_{d_i}\)\(d_i\) 为点 \(i\) 的度数)。

注意到这题有自环,于是我们可以选两个不同的自环,贡献为 \(\operatorname{C}^2_{tot}\)\(tot\) 为自环个数);也可以选一个自环和一个普通边,贡献为 \(tot \times (m-tot)\)

实现
#include<bits/stdc++.h>
#define int long long
using namespace std;const int N=2e6+5;
int n,m;
int d[N],fa[N];
bool vis[N];int fnd(int x){return x==fa[x]?x:fa[x]=fnd(fa[x]);
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n>>m;for(int i=1;i<=n;i++)fa[i]=i;int tot=0;for(int i=1,u,v;i<=m;i++){cin>>u>>v;vis[u]=vis[v]=1;if(u==v){tot++;continue;}d[u]++,d[v]++;u=fnd(u),v=fnd(v);if(u!=v)fa[u]=v;}int root=0;for(int i=1;i<=n;i++)if(fa[i]==i&&vis[i])root++;if(root>1){cout<<0;return 0;}int ans=tot*(tot-1)/2+tot*(m-tot);for(int i=1;i<=n;i++)ans+=d[i]*(d[i]-1)/2;cout<<ans;return 0;
}
http://www.rkmt.cn/news/9077.html

相关文章:

  • CF global round 29 CD
  • go语言复杂的map
  • CF700E Cool Slogans 做题记录
  • 完整教程:在 Ubuntu 上安装和配置 PostgreSQL 实录
  • 一个MCU与FPGA混合电路上电启动的问题及其解决办法探索[原创www.cnblogs.com/helesheng]
  • go语言的结构体和指针
  • 从 C++ 到 Python
  • Nipper 3.9.0 for Windows Linux - 网络设备漏洞评估
  • 实用指南:认知语义学中的象似性对人工智能自然语言处理深层语义分析的影响与启示
  • 完整教程:机器学习入门,用Lima在macOS免费搭建Docker环境,彻底解决镜像与收费难题!
  • 求出e的值
  • 0voice-2.1.1-io多路复用select/poll/epoll
  • comfUI背后的技术——VAE - 实践
  • 实用指南:Maven、Spring Boot、Spring Cloud以及它们的相互关系
  • 第二次软工作业
  • 20250921 模拟赛 T4 题解
  • 1.3 课前问题列表
  • warm-flow 监听器对象获取问题
  • Hexo Butterfly 5.4 分页问题 YAML 错误 解决方法总结
  • 第十一届中国大学生程序设计竞赛网络预选赛(CCPC Online 2025)
  • 完整教程:数据结构 栈和队列、树
  • 酵母双杂交技术:高通量筛选的突破与不可忽视的三大局限性
  • ubuntu20.04测试cuda
  • Promise中处理请求超时问题
  • AI驱动建筑行业数字化转型
  • VSCode 把代码发送到激活状态下的终端
  • 线性结构之数组[基于郝斌课程]
  • 完整教程:Vue中的props方式
  • 完整教程:MySQL 存储过程完整实战手册---一篇吃透 Stored Procedure
  • 「MCOI-05」魔仙