传送门

%%%myy

考虑30分做法:暴力bfs,\(f[i][j]\)表示\(i\)到\(j\)可以形成回文串

然而为什么我场上只想到了70分做法,完全没想到30分怎么写。。

100分:

考虑缩边,对于每条边分3种情况:标号同为1,标号同为0,标号不同

1、同为1:考虑如果这是个二分图,那么可以转化为一颗生成树,对答案无影响,如果不是二分图,那么就随意加一条自环,这样就可以同时出现奇回文和偶回文

2、同为0:同上

3、不同,只有可能是二分图,直接建生成树就好了

这样下来边的数量就是\(O(n)\)级的了

然后再暴力跑bfs就好了,没错,就是那个30分做法,总复杂度\(O(n^2)\)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
void read(int &x){
char ch;bool ok;
for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
#define rg register
const int maxn=1e6+10;queue<pair<int,int> >q;
int n,m,qq,f[5010][5010];char ch[5010];
struct oo{
int cnt,pre[maxn],nxt[maxn],h[maxn],w[maxn];
bool flag;
void add(int x,int y){
pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
}
}a,b,c,d;
void dfs1(int x,int v){
a.w[x]=v;
for(rg int i=a.h[x];i;i=a.nxt[i])
if(a.w[a.pre[i]]!=-1&&a.w[a.pre[i]]==a.w[x])a.flag=1;
else if(a.w[a.pre[i]]==-1)dfs1(a.pre[i],v^1),d.add(a.pre[i],x);
}
void dfs2(int x,int v){
b.w[x]=v;
for(rg int i=b.h[x];i;i=b.nxt[i])
if(b.w[b.pre[i]]!=-1&&b.w[b.pre[i]]==b.w[x])b.flag=1;
else if(b.w[b.pre[i]]==-1)dfs2(b.pre[i],v^1),d.add(b.pre[i],x);
}
void dfs3(int x,int v){
c.w[x]=v;
for(rg int i=c.h[x];i;i=c.nxt[i])
if(c.w[c.pre[i]]!=-1&&c.w[c.pre[i]]==c.w[x])c.flag=1;
else if(c.w[c.pre[i]]==-1)dfs3(c.pre[i],v^1),d.add(c.pre[i],x);
}
#define mk(a,b) make_pair(a,b)
void solve(){
for(rg int i=1;i<=n;i++)f[i][i]=1,q.push(mk(i,i));
for(int x=1;x<=n;x++)
for(int i=d.h[x];i;i=d.nxt[i])
if(ch[x]==ch[d.pre[i]])f[x][d.pre[i]]=1,q.push(mk(x,d.pre[i]));
while(!q.empty()){
pair<int,int> x=q.front();q.pop();
for(rg int i=d.h[x.first];i;i=d.nxt[i])
for(rg int j=d.h[x.second];j;j=d.nxt[j])
if(ch[d.pre[i]]==ch[d.pre[j]]&&!f[d.pre[i]][d.pre[j]])f[d.pre[i]][d.pre[j]]=1,q.push(mk(d.pre[i],d.pre[j]));
}
}
int main()
{
read(n),read(m),read(qq),scanf("%s",ch+1);
for(rg int i=1,x,y;i<=m;i++){
read(x),read(y);
if(ch[x]!=ch[y])a.add(x,y);
else if(ch[x]=='0')b.add(x,y);
else c.add(x,y);
}
memset(a.w,-1,sizeof a.w);
memset(b.w,-1,sizeof b.w);
memset(c.w,-1,sizeof c.w);
for(rg int i=1;i<=n;i++){
if(a.w[i]==-1){
a.flag=0,dfs1(i,0);
if(a.flag)d.add(i,i);
}
if(b.w[i]==-1){
b.flag=0,dfs2(i,0);
if(b.flag)d.add(i,i);
}
if(c.w[i]==-1){
c.flag=0,dfs3(i,0);
if(c.flag)d.add(i,i);
}
}
solve();
for(rg int i=1,x,y;i<=qq;i++){
read(x),read(y);
if(f[x][y])printf("YES\n");
else printf("NO\n");
}
}

bzoj5492:[Hnoi2019]校园旅行的更多相关文章

  1. 【BZOJ5492】[HNOI2019]校园旅行(bfs)

    [HNOI2019]校园旅行(bfs) 题面 洛谷 题解 首先考虑暴力做法怎么做. 把所有可行的二元组全部丢进队列里,每次两个点分别向两侧拓展一个同色点,然后更新可行的情况. 这样子的复杂度是\(O( ...

  2. [HNOI2019]校园旅行(构造+生成树+动规)

    题目 [HNOI2019]校园旅行 做法 最朴素的做法就是点对扩展\(O(m^2)\) 发现\(n\)比较小,我们是否能从\(n\)下手减少边数呢?是肯定的 单独看一个颜色的联通块,如果是二分图,我们 ...

  3. Luogu P5292 [HNOI2019]校园旅行

    非常妙的一道思博题啊,不愧是myy出的题 首先我们考虑一个暴力DP,直接开一个数组\(f_{i,j}\)表示\(i\to j\)的路径能否构成回文串 考虑直接拿一个队列来转移,队列里存的都是\(f_{ ...

  4. [HNOI2019]校园旅行

    题意 https://www.luogu.org/problemnew/show/P5292 思考 最朴素的想法,从可行的二元组(u,v)向外拓展,及u的出边所指的颜色与v的出边所指的颜色若相同,继续 ...

  5. 洛谷P5292 [HNOI2019]校园旅行(二分图+最短路)

    题面 传送门 题解 如果暴力的话,我们可以把所有的二元组全都扔进一个队列里,然后每次往两边更新同色点,这样的话复杂度是\(O(m^2)\) 怎么优化呢? 对于一个同色联通块,如果它是一个二分图,我们只 ...

  6. [LOJ3057] [HNOI2019] 校园旅行

    题目链接 LOJ:https://loj.ac/problem/3057 洛谷:https://www.luogu.org/problemnew/show/P5292 Solution 先膜一发\(m ...

  7. 【洛谷5292】[HNOI2019] 校园旅行(思维DP)

    点此看题面 大致题意: 给你一张无向图,每个点权值为\(0\)或\(1\),多组询问两点之间是否存在一条回文路径. 暴力\(DP\) 首先,看到\(n\)如此之小(\(n\le5000\)),便容易想 ...

  8. [HNOI2019]校园旅行(建图优化+bfs)

    30分的O(m^2)做法应该比较容易想到:令f[i][j]表示i->j是否有解,然后把每个路径点数不超过2的有解状态(u,v)加入队列,然后弹出队列时,两点分别向两边搜索边,发现颜色一样时,再修 ...

  9. 【BZOJ5492】校园旅行(图论 搜索优化)

    题目链接 大意 给出\(N\)个点,\(M\)条边的一张图,其中每个点都有一个0或1的颜色. 再给出\(Q\)个询问,每次询问查询两个点之间是否存在一条路径,使得路径上的颜色组成的01字符串是一个回文 ...

随机推荐

  1. TCP服务器端和客户端程序设计【转】

    本文转载自:http://blog.csdn.net/yueguanghaidao/article/details/7035248# 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.实验目的 ...

  2. 51nod 1610

    题目 神犇题解 所以说鄙人的姿势水平完全不够啊OTZ. 很naive的想法是O(T*v*m)的,据说卡一卡可以过去.题目要求的东西其实是这个: $ \sum\limits_{i = 1}^v {\mu ...

  3. BZOJ 1572 [Usaco2009 Open]工作安排Job:贪心 + 优先队列【先放再更新】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1572 题意: 有n个工作,每个工作有一个截止日期dead[i]和收益pay[i]. 完成一 ...

  4. JavaUtil_03_图片处理工具类

    一.源码 功能:缩放图像.切割图像.图像类型转换.彩色转黑白.文字水印.图片水印等 package com.ray.dingtalk.util; import java.awt.AlphaCompos ...

  5. 苹果手机app试玩赚钱平台汇总

    注意: 微信扫码下载,绑定手机号和微信.才能提现 每天3点更新任务,4点最多! | 平台 | 提现额 | 任务量| 推荐强度 | 扫码 | 1.小鱼,10元,大量,强推! →点开扫码 2.天天飞燕,5 ...

  6. UC Bug

    出现bug时,假如把A代码段删了,bug消失,那么此bug是不是一定就是A代码段导致的呢?接着写B代码段,同样bug再现,那么此bug是不是一定就是B代码段导致的呢? 未必,可能是Base代码段和A. ...

  7. UOJ_14_【UER #1】DZY Loves Graph_并查集

    UOJ_14_[UER #1]DZY Loves Graph_并查集 题面:http://uoj.ac/problem/14 考虑只有前两个操作怎么做. 每次删除一定是从后往前删,并且被删的边如果不是 ...

  8. 「LOJ#6121」「网络流 24 题」孤岛营救问题(BFS

    题目描述 1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图.迷宫的外形是一个长方形 ...

  9. ACM学习历程—Hihocoder编程之美测试赛B题 大神与三位小伙伴(组合数学 )

    时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给你一个m x n (1 <= m, n <= 100)的矩阵A (0<=aij<=10000),要 ...

  10. tyvj 1203 机器分配

    时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 总公司拥有高效生产设备M台,准备分给下属的N个公司.各分公司若获得这些设备,可以为国家提供一定的盈利.问:如何 ...