「AGC027C」 ABland Yard

题意

给定一张无向图,每个点点权为 AB。求对于每一个由 AB 组成的字符串 \(S\),是否在图中存在一条路径满足路径上的点权连在一起为 \(S\),可以重复经过任意一个点和任意一条边。

分析

显然我们需要找到一个环,让路径不断重复在上面走。

考虑一个满足条件的最小环,原图只要存在这种环就满足条件,这个环应该满足每个点的后继都存在 AB

直接找比较困难,为了简化它,可以考虑把不满足的点去掉。

这个过程类似拓扑排序,对每个点记录它后继中 AB 的数量,如果有一个为 \(0\) 就删去这个点。

如果剩下有点,就说明满足条件,否则不满足。

时间复杂度 \(O(n)\)

Code

#include<bits/stdc++.h>
typedef int ll;
using namespace std;
static char buf[100],*p1=buf,*p2=buf,obuf[100],*p3=obuf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++
#define putchar(x) (p3-obuf<100)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
mt19937_64 rnd(chrono::system_clock::now().time_since_epoch().count());
#define dbg(x) cout<<#x<<": "<<x<<"\n"
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
inline void write(ll x){if(!x){putchar(48);putchar('\n');return;}short top=0,s[40];if(x<0)x=-x,putchar(45);while(x)s[top++]=x%10^48,x/=10;while(top--)putchar(s[top]);putchar('\n');}
namespace tobe{
	const ll maxn=2e5+5,mod=998244353;
	ll n,m,cnt[maxn][2];
	string a;
	bool vis[maxn];
	vector<ll>son[maxn];
	inline void mian(){
		n=read(),m=read();
		cin>>a;a=" "+a;
		while(m--){
			ll u=read(),v=read();
			son[u].push_back(v);
			son[v].push_back(u);
			++cnt[u][a[v]-'A'];
			++cnt[v][a[u]-'A'];
		}
		queue<ll>q;
		for(ll i=1;i<=n;++i){
			if(!cnt[i][0]||!cnt[i][1]){
				q.push(i),vis[i]=1;
			}
		}
		while(!q.empty()){
			ll u=q.front();q.pop();
			for(auto v:son[u]){
				if(!--cnt[v][a[u]-'A']&&!vis[v]){
					q.push(v);vis[v]=1;
				}
			}
		}
		ll ans=0;
		for(ll i=1;i<=n;++i)ans+=!vis[i];
		if(ans)puts("Yes");
		else puts("No");
	}
}
signed main(){
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	ll t=1;
	while(t--)tobe::mian();
	fwrite(obuf,p3-obuf,1,stdout);
	return 0;
}
posted @ 2024-12-20 15:31  run-away  阅读(13)  评论(0)    收藏  举报