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;
}

 

posted @   GSHDYJZ  阅读(219)  评论(0编辑  收藏  举报
编辑推荐:
· 深入理解 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 构建精确任务处理应用
点击右上角即可分享
微信分享提示