【2020.11.23提高组模拟】徒(walk) 题解

题目描述

给一个简单连通无向图,选一个点为起点,每次选一条没有走过的边走,若无则停止。问是否存在一个起点使得无论如何选择,走出来的路径一定是欧拉路。

\(T\le 10,n\le100000,m\le200000\)

Solution

这是一道结论题。

首先要存在欧拉路,才可能存在那样的一个起点。这个先特判。

接下来有一个结论。

结论:

对于所有点度都是偶数的图,若存在一个点被所有环经过,则存在那样的起点且就是被所有环穿过的点,否则不行

对于有两个点度是奇数的图,若存在一个奇度点被所有环经过,才存在,否则不存在。

证明:

对于所有点度都是偶数的图,若存在一个点被所有点经过,我们设这个点为起点,假设我们已经走了一些欧拉回路并且有一些点没有走,那么由于欧拉回路中的所有点的度数为偶数,可以发现剩下边组成的图的点的度数还是偶数,那么剩下的边组成的图中一定是欧拉图集合,其中一定有环。又因为起点就是在环上的,所以可以直接走,一定有解。

若不存在一个点被所有的环穿过,则一定可以构造出一种不符合要求的方案。

奇数的类似证明。

而判断一个点是否在所有环上只需要删除这个点以及其边,图若变成森林(找不到环),则这个点是合法的。这样是\(O(n^2)\)的。

考虑当点度数都是偶数时贪心,发现起点一定是度数最大的点,因此可以一遍找环即可。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std; template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int q;
int n,m;
int head[400010],nxt[400010],ver[400010];
bool book[400010],unexist[400010];
int degree[100010];
int cnt;
void insert(int x,int y)
{
nxt[++cnt]=head[x];
ver[cnt]=y;
head[x]=cnt; nxt[++cnt]=head[y];
ver[cnt]=x;
head[y]=cnt;
degree[x]++;
degree[y]++;
}
void init()
{
memset(head,0,sizeof(nxt));
memset(degree,0,sizeof(degree));
cnt=1;
}
bool dfs(int x,int fa)
{
if(book[x]) return 1;
book[x]=1;
for(re int i=head[x];i;i=nxt[i])
{
if(unexist[i]||ver[i]==fa) continue;
if(dfs(ver[i],x)) return 1;
}
return 0;
}
bool work(int s)
{
memset(book,0,sizeof(book));
memset(unexist,0,sizeof(unexist));
for(int i=head[s];i;i=nxt[i]) unexist[i]=unexist[i^1]=1;
for(int i=1;i<=n;i++)
{
if(i==s||book[i]) continue;
if(dfs(i,i)) return 0;
}
return 1;
}
int main()
{
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
q=read();
while(q--)
{
init();
n=read();
m=read();
for(re int i=1;i<=m;i++)
insert(read(),read());
int flag=0;
for(int i=1;i<=n&&flag<=2;i++)
if(degree[i]&1) flag++;
if(flag!=0&&flag!=2)
{
cout<<"NO"<<endl;
continue;
}
if(!flag)
{
re int s,sd=0;
for(re int i=1;i<=n;i++)
if(sd<degree[i]) sd=degree[i],s=i;
if(work(s)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
else
{
re bool flag2=0;
for(re int i=1;i<=n&&!flag2;i++)
{
if(degree[i]&1)
{
if(work(i))
flag2=1;
}
}
if(flag2) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}

End

写代码的时候没带脑子。

没了。

【2020.11.23提高组模拟】徒(walk) 题解的更多相关文章

  1. 【2020.11.28提高组模拟】T1染色(color)

    [2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...

  2. 【2020.11.28提高组模拟】T2 序列(array)

    序列(array) 题目描述 ​给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...

  3. 【2020.11.30提高组模拟】剪辣椒(chilli)

    剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...

  4. 【2020.11.30提高组模拟】删边(delete)

    删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...

  5. JZOJ 【2020.11.30提高组模拟】剪辣椒(chilli)

    题目大意 给出一棵 \(n\) 个节点的树,删去其中两条边 使得分出的三个子树大小中最大与最小的差最小 分析 先一边 \(dfs\) 预处理出以 \(1\) 为根每个点的 \(size\) 然后按 \ ...

  6. JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)

    题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...

  7. 11.5NOIP2018提高组模拟题

    书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...

  8. 【2020.12.03提高组模拟】A组反思

    估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...

  9. 【2020.12.01提高组模拟】卡特兰数(catalan)

    题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...

  10. 【2020.12.01提高组模拟】A组反思

    105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...

随机推荐

  1. 【Verilog】表达式位宽与符号判断机制

    缘起于p1课下alu算数位移设计.查了好多资料,最后发现还是主要在翻译官方文档.浪费了超多时间啊,感觉还是没搞透,还是先以应用为导向放一放,且用且归纳 1.表达式位宽 expression bit l ...

  2. halo配置踩坑过程小记

    写在最前: ​ 终于搞定了最后的一步域名解析配置,其实动态博客的折腾程度也不低于当时的hexo吧,也可能当时的痛苦过程已经忘了..整理一下思路,记录一下配置过程走过的坑. ​ 我是从hexo用了半年想 ...

  3. Vim 操作-替换

    Vim 操作-替换 substitute :[range]s[ubstitute]/{pattern}/{string}/{flag} 替换的操作范围以行为基础: %-全局范围,m,n-使用逗号隔开的 ...

  4. storm部署文档

    背景 这篇笔记原来是记录在印象笔记中的,没有发布到博客中,这次我重新整理一下发布上来,希望给读者以参考. Storm的部署手册 Zookeepr的部署 首先下载安装包:apache-zookeeper ...

  5. PHP配置并使用mosquitto

    要在PHP中配置和使用Mosquitto,你需要进行以下步骤: 安装Mosquitto PHP扩展: sudo apt-get install php-mosquitto 在PHP配置文件中启用Mos ...

  6. String常见面试题

    第一题:打印的结果是true还是false呢? 在之前我们就说过这题,执行s1时,检查字符串常量池,发现没有"abc",于是创建"abc",执行s2时,接着检查 ...

  7. 如何查看 linux 发行版本

    以 debian 10 buster 为例 有时候我们需要知道当前正在使用的 linux 的发行版本信息...可以通过下面几种方式来查看 使用 lsb_release 命令查看 lsb_release ...

  8. 要命的DRG成本核算!

    改开几十年的三座大山之一,鬼见愁的问题.会随着DRG的推进而让平头老百姓过上翻身做主的日子呢!? 对于DRG,首先医保部门需要了解病种成本状况,确定给你结算多少银子.第二,咱们医院靠医保吃饭,那就更需 ...

  9. Hyperledger Fabric - 区块链应用

    Fabric Gateway SDK 实现Fabric的编程模型,提供了一系列简单的API给应用程序与Fabric区块链网络进行交互 应用程序将各自的网络交互委托给其网关,每个网关都了解网络信道拓扑, ...

  10. PHP传递参数(跨文件)的8种常见方法

    以下是 PHP 中跨文件传递参数的 8 种常见方法,按场景和安全性分类整理,附详细说明和示例代码: 一.超全局变量(适合请求间数据共享) 1. $_GET / $_POST 用途:通过 URL 或表单 ...