Description
给一个n个点m条边的无向图,每个点有个权值0或1。q次询问x,y求是否存在一条从x到y的路径使得经过节点的权值连接起来是一个回文串
n
≤
5
e
3
,
m
≤
5
e
5
n\le5e3,m\le5e5
n≤5e3,m≤5e5
Solution
这个是loj加强过的数据。。原题好像是3e3的
m2的做法就是按照原图dp,设f[x,y]表示x到y有一条合法路径,枚举x和y的邻边转移就可以做到m2。实现的时候开一个队列,像bfs一样把新增的合法路径扔进队尾就可以了
可以发现瓶颈在于边数太多了。考虑按照颜色把边分成3类,嘿嘿、嘿掰、掰掰边。可以发现现在经过一个连通块的路径颜色都是一样的,这样就只和路径长度相关了。由于我们可以反复经过一个点,那么就只和奇偶性有关了。
考虑按照是否存在奇环把连通块分两类。
若不存在奇环,那么我们可以把连通块黑白染色,一条从黑点到白点的路径长度的奇偶性就是确定的。所以我们只需要保留原连通块的连通性,原本绕圈的操作可以通过反复横跳凑够。
若存在奇环,那么就会出现奇偶性改变的情况,这个时候我们只需要随便找个点x连一个自环就行了。可以发现这样就能实现反复横跳的同时改变奇偶性。
然后我们就成功地把边数降到了O(n)级别,套用上面那个做法就可以A辣
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=2005;
const int E=50005;
std:: vector <int> G[N];
std:: queue <int> que;
struct Graph {
struct edge {int x,y,next;} e[E];
int d[N],ls[N],edCnt;
int c[N],flag;
void add_edge(int x,int y) {
e[++edCnt]=(edge) {x,y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {y,x,ls[y]}; ls[y]=edCnt;
}
void dfs(int x,int id) {
c[x]=id;
for (int i=ls[x];i;i=e[i].next) {
if (c[e[i].y]==-1) {
dfs(e[i].y,!id);
G[x].push_back(e[i].y);
G[e[i].y].push_back(x);
} else if (c[e[i].y]==id) flag=true;
}
}
void build(int n) {
rep(i,1,n) c[i]=-1;
rep(i,1,n) if (c[i]==-1) {
flag=false;
dfs(i,1);
if (flag) G[i].push_back(i);
}
}
} BB,BW,WW;
bool f[N][N];
char s[N];
void ins(int x,int y) {
if (x>y) std:: swap(x,y);
if (f[x][y]) return ;
que.push(x),que.push(y);
f[x][y]=f[y][x]=1;
}
int main(void) {
freopen("data.in","r",stdin);
int n,m,k; scanf("%d%d%d",&n,&m,&k);
scanf("%s",s+1);
rep(i,1,n) ins(i,i);
rep(i,1,m) {
int x,y; scanf("%d%d",&x,&y);
if (s[x]==s[y]) {
if (s[x]=='1') BB.add_edge(x,y);
else WW.add_edge(x,y);
ins(x,y);
} else BW.add_edge(x,y);
}
BB.build(n),WW.build(n),BW.build(n);
for (;!que.empty();) {
int x=que.front(); que.pop();
int y=que.front(); que.pop();
for (int i=0;i<G[x].size();++i) {
for (int j=0;j<G[y].size();++j) {
int a=G[x][i],b=G[y][j];
if (s[a]==s[b]) ins(a,b);
}
}
}
for (;k--;) {
int x,y; scanf("%d%d",&x,&y);
puts(f[x][y]?"YES":"NO");
}
return 0;
}