UOJ#465. 【HNOI2019】校园旅行 其他
原文链接www.cnblogs.com/zhouzhendong/p/UOJ465.html
前言
tmd并查集写挂,调到自闭。
cly和我写挂了同一个地方。
一下救了两个人感觉挺开心。
题解
首先直接写 bfs/记忆化dfs 可以容易地得到一个 $O(m^2)$ ,或者 $O(nm)$ 的做法。常数不大的情况下应该可以得到 70 分。
注意到本题中不要求简单路径,同一条边可以经过多次。
这意味着,我们可以在有边相连的两个同色节点之间来回走。
那么,假设两个点在同一个同色连通块,那么从其中一个点到另一个点的路径的有效信息本质只有两种:是否存在长度为奇数的路径、是否存在长度为偶数的路径。
于是,对于一个同色连通块,我们只需要保留一个带奇环的基环树即可,如果没有满足条件的基环树,就保留一个树。
然后我们考虑拆除所有连接同色点的边,留下所有连接不同色点的边。
类似的,对于剩下的边,我们只要留下一座边数尽量多的生成森林即可。
我丝薄了,写了个并查集维护。其实直接 dfs 就好了。
于是剩下 $O(n)$ 条边,只要做一做最开始的暴力就好了。
时间复杂度 $O(m\cdot \alpha(n) + n^2)$ 或 $O(m + n ^2)$ 。
代码
#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define real __zzd001
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> vi;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=5005,M=500005;
int n,m,q;
vector <int> e[N];
char s[N];
struct Edge{
int x,y;
}E[M];
int r[N];
namespace S1{
int fa[N],d[N];
void init(){
For(i,1,n)
fa[i]=i;
clr(d);
}
int getf(int x){
if (fa[x]==x)
return x;
int f=getf(fa[x]);
d[x]^=d[fa[x]];
return fa[x]=f;
}
}
namespace S2{
int fa[N];
void init(){
For(i,1,n)
fa[i]=i;
}
int getf(int x){
return fa[x]==x?x:fa[x]=getf(fa[x]);
}
}
int f[N][N];
int qx[N*N],qy[N*N],head=0,tail=0;
void Push(int x,int y){
if (x>y)
swap(x,y);
if (!f[x][y]){
f[x][y]=1;
tail++;
qx[tail]=x;
qy[tail]=y;
}
}
int main(){
n=read(),m=read(),q=read();
scanf("%s",s+1);
For(i,1,m)
E[i].x=read(),E[i].y=read();
S1::init(),S2::init();
For(i,1,m){
int x=E[i].x,y=E[i].y;
if (s[x]==s[y]){
if (S1::getf(x)!=S1::getf(y)){
e[x].pb(y),e[y].pb(x);
S1::d[S1::getf(x)]=S1::d[x]^S1::d[y]^1;
S1::fa[S1::fa[x]]=S1::getf(y);
}
}
else {
if (S2::getf(x)!=S2::getf(y)){
e[x].pb(y),e[y].pb(x);
S2::fa[S2::getf(x)]=S2::getf(y);
}
}
}
For(i,1,m){
int x=E[i].x,y=E[i].y;
S1::getf(x),S1::getf(y);
if (s[x]==s[y]&&!r[S1::getf(x)]&&S1::d[x]==S1::d[y]){
r[S1::getf(x)]=1;
e[x].pb(y),e[y].pb(x);
}
}
For(i,1,n)
Push(i,i);
For(i,1,m)
if (s[E[i].x]==s[E[i].y])
Push(E[i].x,E[i].y);
while (head<tail){
head++;
int x=qx[head],y=qy[head];
for (auto a : e[x])
for (auto b : e[y])
if (s[a]==s[b])
Push(a,b);
}
while (q--){
int x=read(),y=read();
if (x>y)
swap(x,y);
puts(f[x][y]?"YES":"NO");
}
return 0;
}
UOJ#465. 【HNOI2019】校园旅行 其他的更多相关文章
- 【BZOJ5492】[HNOI2019]校园旅行(bfs)
[HNOI2019]校园旅行(bfs) 题面 洛谷 题解 首先考虑暴力做法怎么做. 把所有可行的二元组全部丢进队列里,每次两个点分别向两侧拓展一个同色点,然后更新可行的情况. 这样子的复杂度是\(O( ...
- [HNOI2019]校园旅行(构造+生成树+动规)
题目 [HNOI2019]校园旅行 做法 最朴素的做法就是点对扩展\(O(m^2)\) 发现\(n\)比较小,我们是否能从\(n\)下手减少边数呢?是肯定的 单独看一个颜色的联通块,如果是二分图,我们 ...
- Luogu P5292 [HNOI2019]校园旅行
非常妙的一道思博题啊,不愧是myy出的题 首先我们考虑一个暴力DP,直接开一个数组\(f_{i,j}\)表示\(i\to j\)的路径能否构成回文串 考虑直接拿一个队列来转移,队列里存的都是\(f_{ ...
- [HNOI2019]校园旅行
题意 https://www.luogu.org/problemnew/show/P5292 思考 最朴素的想法,从可行的二元组(u,v)向外拓展,及u的出边所指的颜色与v的出边所指的颜色若相同,继续 ...
- 洛谷P5292 [HNOI2019]校园旅行(二分图+最短路)
题面 传送门 题解 如果暴力的话,我们可以把所有的二元组全都扔进一个队列里,然后每次往两边更新同色点,这样的话复杂度是\(O(m^2)\) 怎么优化呢? 对于一个同色联通块,如果它是一个二分图,我们只 ...
- [LOJ3057] [HNOI2019] 校园旅行
题目链接 LOJ:https://loj.ac/problem/3057 洛谷:https://www.luogu.org/problemnew/show/P5292 Solution 先膜一发\(m ...
- 【洛谷5292】[HNOI2019] 校园旅行(思维DP)
点此看题面 大致题意: 给你一张无向图,每个点权值为\(0\)或\(1\),多组询问两点之间是否存在一条回文路径. 暴力\(DP\) 首先,看到\(n\)如此之小(\(n\le5000\)),便容易想 ...
- bzoj5492:[Hnoi2019]校园旅行
传送门 %%%myy 考虑30分做法:暴力bfs,\(f[i][j]\)表示\(i\)到\(j\)可以形成回文串 然而为什么我场上只想到了70分做法,完全没想到30分怎么写.. 100分: 考虑缩边, ...
- [HNOI2019]校园旅行(建图优化+bfs)
30分的O(m^2)做法应该比较容易想到:令f[i][j]表示i->j是否有解,然后把每个路径点数不超过2的有解状态(u,v)加入队列,然后弹出队列时,两点分别向两边搜索边,发现颜色一样时,再修 ...
- Loj #3057. 「HNOI2019」校园旅行
Loj #3057. 「HNOI2019」校园旅行 某学校的每个建筑都有一个独特的编号.一天你在校园里无聊,决定在校园内随意地漫步. 你已经在校园里呆过一段时间,对校园内每个建筑的编号非常熟悉,于是你 ...
随机推荐
- 第一周java学习总结
学号 20175206 <Java程序设计>第一周学习总结 教材学习内容总结 第一章是关于JAVA入门的注意事项: 第一章主要按照顺序讲了JAVA的地位,诞生,特点,JDK的安装,一些ja ...
- CH4INRULZ从渗透到提权
下载了镜像后查看了ip http://192.168.16.128/ 然后用nmap扫描了一波 sudo nmap -vv -sV 192.168.16.128 访问80端口发现是个个人博客 访问80 ...
- Typora 使用说明
目录 Typora是一款超简洁的markdown编辑器,具有如下特点: 完全免费,目前已支持中文 跨平台,支持windows,mac,linux 支持数学公式输入,图片插入 极其简洁,无多余功能 界面 ...
- python常用的内置函数哈哈
python常用的内置函数集合做一个归类用的时候可以查找 abs 返回数字x的绝对值或者x的摸 all (iterable)对于可迭代的对象iterable中所有元素x都有bool(x)为true,就 ...
- jqGrid整合篇
jqgrid实现多级表头 //使用setGroupHeaders参数: $( "#datagrid" ).jqGrid( 'setGroupHeaders' , { useColS ...
- KML,SHP TAB互转,GDAL
最近在接触地图数据转换的东西,从硬件kml的数据转换其他的格式,因为从没做过着东西, 先去了解kml文件格式 http://baike.baidu.com/view/400307.htm?fr=ala ...
- 从koa-session源码解读session本质
前言 Session,又称为"会话控制",存储特定用户会话所需的属性及配置信息.存于服务器,在整个用户会话中一直存在. 然而: session 到底是什么? session 是存在 ...
- ABP学习之路--切换mysql数据库
1.添加mysql相关引用 注意,使用最新版本会导数据迁移时出错 2.修改链接字符串: <add name="Default" connectionString=" ...
- python正则表达式--分组、后向引用、前(后)向断言
无名.有名分组 (1)正则表达式—无名分组 从正则表 达式的左边开始看,看到的第一个左括号“(”表示表示第一个分组,第二个表示第二个分组, 依次类推. 需要注意的是,有一个隐含的全局分组(就是索引号为 ...
- FhqTreap的区间翻转
学 Fhq 就是为了尽量不去写某毒瘤数据结构,所以自然要来杠一杠某数据结构的经典操作:区间反转 听起来玄乎,但只需要一个小 trick 就行了:把原来的区间以下标作为权值建成 Treap , 这样整棵 ...