GotoAndPlay 图论
10月3日,在杭州市西湖景区,一只小松鼠不停地接受一道道食物,花生、
玉米、饼干,可谓来者不拒,憨态可掬的模样吸引了众多围观者...
Description
小松鼠终于吃撑了,她决定逃离这个地方。
我们用一张连通图来表示整个西湖的范围,每棵容小松鼠逗留的树都用
这张图上的一个点来表示。小松鼠能够通过只跳一次互相到达的两棵树用
图上的一条无向边来连接。
吃撑了的小松鼠有些神志不清,每次她连跳两条边之后才会在到达的那
个点上休息。她想知道,是否存在一种连续的跳法,使得她有机会在所有
的树上都休息至少一次。
对于这种跳法,你可以任选起点,允许重复经过边,允许重复经过点。
但是超萌小松鼠是一只有梦想的小松鼠,她有时能够突破自己的极限,
使一些原本无法互相到达的两个点能够通过一次跳跃互相到达。
Input
第一行两个数n,m。n表示点的个数,m表示边的条数
接下来m行,每行两个数x i ,y i ,表示x i 和y i 之间能够通过一次跳跃互相到
达。
接下来一行一个数q,表示询问的个数。
接下来q行,其中的第i行每行两个数a i ,b i 。表示在原图的基础上加上从a i 到b i 的
边。即成为一张n个点m + 1条边的图。
保证给出的原图是个连通图,1 <= a i , b i , x i , y i <= n。
Output
输出一共q行,对于第i个询问,当在原图的基础上加上a i 与b i 间的无向边
后,如果小松鼠能够找到一种连续的跳法,使得她有机会在所有的树上至
少休息一次,输出一行“Yes”,否则输出一行“No” 。 (不包含引号)
Constraints
对于前50%,n, q <= 10 3 , m <= 2 × 10 3 。
对于100%,n, q <= 10 5 , m <= 2 × 10 5 。
首先直接暴力,每次查询的时候就直接加两条边然后走一遍,看看可不可以走完,这样做可以拿到50分。
然后我们来想想正解,
看到每次跳两下,我们可能会想到二分图染色,但是二分图染色法为什么是对的呢?
假设我们染完色后,询问给出x,y,如果他们两个时同一种颜色,那么就可以联通(每次走两步,正好把二分图连起来了),否则不联通。
这样我们就可以快速判断该图是否联通。
并且还要注意,如果原图在染色时被判定不是二分图,那我们对于每次询问都可以直接输出联通了。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define ll long long #define il inline #define db double using namespace std; il int gi() { int x=0,y=1; char ch=getchar(); while (ch< '0' ||ch> '9' ) { if (ch== '-' ) y=-1; ch=getchar(); } while (ch>= '0' &&ch<= '9' ) { x=x*10+ch- '0' ; ch=getchar(); } return x*y; } int head[200045],cnt; struct edge { int next,to; }e[200045]; il void add( int from , int to) { e[++cnt].next=head[ from ]; e[cnt].to=to; head[ from ]=cnt; } int fa[100045]; int find( int x) { if (fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } int color[100045]; bool vis[100045]; int flag; void dfs( int x, int y) { if (vis[x]) { if (y!=color[x]) flag=1; return ; } vis[x]=1; color[x]=y; int r=head[x]; while (r!=-1) { int now=e[r].to; dfs(now,(y+1)%2); r=e[r].next; } } int main() { freopen( "GotoAndPlay.in" , "r" ,stdin); freopen( "GotoAndPlay.out" , "w" ,stdout); memset(head,-1, sizeof (head)); int n=gi(),m=gi(),x,y; for ( int i=1;i<=m;i++) { x=gi(),y=gi(); add(x,y); add(y,x); } dfs(1,0); int q=gi(); for ( int i=1;i<=q;i++) { x=gi(),y=gi(); if (flag==1) printf( "Yes\n" ); else { if (color[x]==color[y]) printf( "Yes\n" ); else printf( "No\n" ); } } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用