<h1>题目描述</h1>
题目链接
给出一个 $N$ 个点、 $M$ 条边的无向图(节点编号 $1~N$ )。每个节点有一个值 A 或 B,你可以从任意一个节点出发,经过一些节点后(可以重复经过),你将经过的节点的值顺次写出来,就可以得到一个只包含 A 或 B 的字符串。求对于只包含 A 或 B 的字符串 $S$ 都找得到一个合法的访问序列使得得到的字符串恰好为 $S$ 。
<h1>题解</h1>
显然如果存在一个类似于 AABB 的环就可以满足所有的条件。于是题目变成了判断图里有没有这样的环。
这个结论证明很好证明:如果这个环里 A 或 B 的个数小于1,那么无法构成 AA 或 BB。
如果这个环里连续 A 或 B 的个数超过 2,则存在一个结尾为 ABBA 或 BAAB 无法构成。
我们判断可以类比拓扑排序的方法,将所有只与 A 或 B 相连的点删除,不断进行知道不能删除为止。
剩下的就一定是形如 AABB 的环了。
<h1>代码</h1>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define Re register
#define LL long long
#define U unsigned
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------n")
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const int MAXN = 200000+5;
struct Node{
struct Edge *firstEdge;
int d[2];bool vis;
int num;
}node[MAXN];
struct Edge{
Node s,t;
Edge *next;
}pool[MAXN<<1],*frog = pool;
Edge New(Node s,Node *t){
Edge *ret = ++frog;
*ret = (Edge){s,t,s->firstEdge};
return ret;
}
char str[MAXN];
inline void add(int u,int v){
node[u].firstEdge = New(&node[u],&node[v]);
++node[u].d[str[v]-'A'];
}
int N,M;
int main(){
scanf("%d%d",&N,&M);
scanf("%s",str+1);
FOR(i,1,N) node[i].num = i;
FOR(i,1,M){
int u,v;scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
std::queue<Node *> q;
FOR(i,1,N) if(!node[i].d[0] || !node[i].d[1]) q.push(&node[i]),node[i].vis = true;
int cnt = q.size();
while(!q.empty()){
Node *v = q.front();q.pop();
for(Edge *e = v->firstEdge;e;e = e->next){
if(!--e->t->d[str[v->num]-'A'] && !e->t->vis){
q.push(e->t);cnt++;
e->t->vis = true;
}
}
}
puts(cnt != N ? "Yes" : "No");
return 0;
}