Loj #3057. 「HNOI2019」校园旅行
Loj #3057. 「HNOI2019」校园旅行
某学校的每个建筑都有一个独特的编号。一天你在校园里无聊,决定在校园内随意地漫步。
你已经在校园里呆过一段时间,对校园内每个建筑的编号非常熟悉,于是你情不自禁的把周围每个建筑的编号都记了下来——但其实你没有真的记下来,而是把每个建筑的编号除以 \(2\) 取余数得到 \(0\) 或 \(1\),作为该建筑的标记,多个建筑物的标记连在一起形成一个 \(01\) 串。
你对这个串很感兴趣,尤其是对于这个串是回文串的情况,于是你决定研究这个问题。
学校可以看成一张图,建筑是图中的顶点,而某些顶点之间存在无向边。对于每个顶点我们有一个标记(\(0\) 或者 \(1\))。每次你会选择图中两个顶点,你想知道这两个顶点之间是否存在一条路径使得路上经过的点的标记形成一个回文串。
一个回文串是一个字符串使得它逆序之后形成的字符串和它自己相同,比如 \(010\),\(1001\) 都是回文串,而 \(01\),\(110\) 不是。注意长度为 \(1\) 的串总是回文串,因此如果询问的两个顶点相同,这样的路径总是存在。此外注意,经过的路径不一定为简单路径,也就是说每条边每个顶点都可以经过任意多次。
输入格式
第一行三个整数 \(n,m,q\),表示图中的顶点数和边数,以及询问数。
第二行为一个长度为 \(n\) 的 \(01\) 串,其中第 \(n\) 个字符表示第 \(i\) 个顶点(即顶点 \(i\))的标记,点从 \(1\) 开始编号。
接下来 \(m\) 行,每一行是两个整数 \(u_i,v_i\),表示顶点 \(u_i\) 和顶点 \(v_i\) 之间有一条无向边,不存在自环或者重边。
接下来 \(q\) 行,每一行存在两个整数 \(x_i,y_i\),表示询问顶点 \(x_i\) 和顶点 \(y_i\) 的点之间是否有一条满足条件的路径。
输出格式
输出 \(q\) 行,每行一个字符串 YES
,或者 NO
。输出 YES
表示满足条件的路径存在,输出 NO
表示不存在。
样例
样例输入 1
5 4 2
00010
4 5
1 3
4 2
2 5
3 5
1 3
样例输出 1
NO
YES
样例说明 1
对于第一个询问,\(3\) 号点和 \(2\) 号点不连通, 因此答案为 NO
。
对于第二个询问,一条合法的路径是 \(1 \to 3\),路径上的标号形成的字符串为 \(00\)。注意合法路径不唯一。
样例输入 2
10 11 10
0011011111
4 6
10 6
5 9
4 7
10 7
5 8
1 9
5 7
1 10
5 1
5 6
10 3
7 4
8 10
9 4
8 9
6 6
2 2
9 9
10 9
3 4
样例输出 2
NO
YES
YES
NO
YES
YES
YES
YES
YES
NO
数据范围与提示
对于 \(30\%\) 的数据,\(1 \le m \le 10^4\);
对于 \(70\%\) 的数据,\(1\le n\le 3\times 10^3,1 \le m \le 5\times 10^4\);
对于 \(100\%\) 的数据,\(1 \le n \le 5\times 10^3, 1 \le m \le 5\times 10^5, 1 \le q \le 10^5\)。
首先很容易想到暴力两边并行\(DFS\)的做法,这样复杂度是\(O(m^2)\)的。
然后考虑优化建边。
对于同种颜色的联通块,如果它是个二分图就保留一个生成树边就行了。因为对于一条非树边,它一定在一个偶环上。假设现在走到\(a,b\),然后\(a\)要走非树边,那么我们实际上随便走一个环,然后\(b\)就找一个相邻的同色节点(如果有的话)反复横跳,因为是偶环,所以是等价的。
如果不是一个二分图,那么我们依然保留非树边,然后随便从一个点连一个子环。因为我们可以改变路径的奇偶。
对于两边颜色不同的边,他们组成的图一定是一个二分图。
代码:
#include<bits/stdc++.h>
#define ll long long
#define N 5005
#define M 1000005
#define Q 100005
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
int n,m,q;
struct road {
int to,nxt;
}s[M<<1];
int h[N],cnt;
void add(int i,int j) {
s[++cnt]=(road) {j,h[i]};h[i]=cnt;
}
vector<int>e[N];
bool ans[N][N];
char str[N];
int col[N];
#define pr pair<int,int>
#define mp(a,b) make_pair(a,b)
queue<pr>que;
vector<pr>vec;
void bfs() {
for(int i=0;i<vec.size();i++) {
int a=vec[i].first,b=vec[i].second;
if(a>b) swap(a,b);
ans[a][b]=1;
que.push(mp(a,b));
}
while(!que.empty()) {
int x=que.front().first,y=que.front().second;
que.pop();
for(int i=h[x];i;i=s[i].nxt) {
for(int j=h[y];j;j=s[j].nxt) {
int a=s[i].to,b=s[j].to;
if(col[a]!=col[b]) continue ;
if(a>b) swap(a,b);
if(!ans[a][b]) {
ans[a][b]=1;
que.push(mp(a,b));
}
}
}
}
}
int f[N];
int Getf(int v) {return v==f[v]?v:f[v]=Getf(f[v]);}
int flag;
int w[N];
void dfs(int v,int Col) {
w[v]=Col;
for(int i=0;i<e[v].size();i++) {
int to=e[v][i];
if(w[to]==-1) {
add(v,to),add(to,v);
dfs(to,Col^1);
} else if(w[v]==w[to]) flag=0;
ans[v][to]=ans[to][v]=1;
que.push(mp(min(v,to),max(v,to)));
}
}
int main() {
n=Get(),m=Get(),q=Get();
scanf("%s",str+1);
for(int i=1;i<=n;i++) col[i]=str[i]-'0';
for(int i=1;i<=n;i++) f[i]=i;
int a,b;
for(int i=1;i<=m;i++) {
a=Get(),b=Get();
if(col[a]!=col[b]) {
if(Getf(a)!=Getf(b)) {
add(a,b),add(b,a);
f[Getf(a)]=Getf(b);
}
} else {
e[a].push_back(b),e[b].push_back(a);
}
if(a>b) swap(a,b);
if(col[a]==col[b]) vec.push_back(mp(a,b));
}
for(int i=1;i<=n;i++) vec.push_back(mp(i,i));
memset(w,-1,sizeof(w));
for(int i=1;i<=n;i++) {
if(w[i]!=-1) continue ;
flag=1;
dfs(i,0);
if(!flag) add(i,i);
}
bfs();
while(q--) {
a=Get(),b=Get();
if(a>b) swap(a,b);
if(ans[a][b]) cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}
Loj #3057. 「HNOI2019」校园旅行的更多相关文章
- LOJ 3057 「HNOI2019」校园旅行——BFS+图等价转化
题目:https://loj.ac/problem/3057 想令 b[ i ][ j ] 表示两点是否可行,从可行的点对扩展.但不知道顺序,所以写了卡时间做数次 m2 迭代的算法,就是每次遍历所有不 ...
- 「loj3057」「hnoi2019」校园旅行
题目 一个n个点m条边的无向图,每个点有0 / 1 的标号; 有q个询问,每次询问(u,v)直接是否存在回文路径(可以经过重复的点和边); $1 \le n \le 5 \times 10^3 , ...
- Loj #3059. 「HNOI2019」序列
Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
- Loj #3055. 「HNOI2019」JOJO
Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...
- Loj 3058. 「HNOI2019」白兔之舞
Loj 3058. 「HNOI2019」白兔之舞 题目描述 有一张顶点数为 \((L+1)\times n\) 的有向图.这张图的每个顶点由一个二元组 \((u,v)\) 表示 \((0\le u\l ...
- LOJ 3059 「HNOI2019」序列——贪心与前后缀的思路+线段树上二分
题目:https://loj.ac/problem/3059 一段 A 选一个 B 的话, B 是这段 A 的平均值.因为 \( \sum (A_i-B)^2 = \sum A_i^2 - 2*B \ ...
- LOJ 3056 「HNOI2019」多边形——模型转化+树形DP
题目:https://loj.ac/problem/3056 只会写暴搜.用哈希记忆化之类的. #include<cstdio> #include<cstring> #incl ...
- LOJ 3055 「HNOI2019」JOJO—— kmp自动机+主席树
题目:https://loj.ac/problem/3055 先写了暴力.本来想的是 n<=300 的那个在树上暴力维护好整个字符串, x=1 的那个用主席树维护好字符串和 nxt 数组.但 x ...
随机推荐
- IdnentiyServer-使用客户端凭据访问API
情景如下:一个客户端要访问一个api,不需要用户登录,但是又不想直接暴露api给外部使用,这时可以使用identityserver添加访问权限. 客户端通过clientid和secrect访问iden ...
- Element-UI 日期范围 date-picke
实际项目应用案例: <el-form-item label="开始日期:" prop="StartDate"> <el-date-picker ...
- 26.C++- 泛型编程之类模板(详解)
在上章25.C++- 泛型编程之函数模板(详解) 学习了后,本章继续来学习类模板 类模板介绍 和函数模板一样,将泛型思想应用于类. 编译器对类模板处理方式和函数模板相同,都是进行2次编译 类模板通 ...
- spring2.0:The server time zone value 'Ãùú±êüñ¼ä' is unrecognized or represents more than one time zone. You must configure either th
提示系统时区出现错误,可以在mysql中执行命令: set global time_zone='+8:00' 或者在数据库驱动的url后加上serverTimezone=UTC参数 jdbc:mysq ...
- Myeclipse 添加插件
配置方式添加插件,添加一个反编译插件示例 1.官网下载(http://java-decompiler.github.io/) 2.下载到本地之后,删除多余的文件(其他的插件也是如此,例如SVN) 3. ...
- JS的函数节流(throttle)
什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在 ...
- HTML5中的input type为file控件限制上传文件类型及扩展
简单介绍 input file控件限制上传文件类型如下:1.文件类型中间用,分开:2.html和htm这样的要写成两个: 3实例: <input type="file" na ...
- C#基础(203)实例方法和重载方法总结,构造方法与实例方法总结,this关键字
c#方法的重载:分为实例方法重载和静态方法重载俩种 1.实例方法重载的调用特点 首先写三个Add方法和三个Sub方法 public int Add(int a,int b) { return a + ...
- 【代码笔记】Web-JavaScript-javascript while循环
一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- HTML元素被定义为块级元素或内联元素。那么什么是块级元素,什么是内联元素呢
块级元素(block)特性: 块级元素在浏览器显示时,通常会以新行来开始(和结束). 宽度(width).高度(height).内边距(padding)和外边距(margin)都可控制;就像以前用到的 ...