题解:CF2179F Blackslex and Another RGB Walking
思路讲解
1. 关键引理:二分图把“同层边”彻底排掉
以点 1 为根,定义
对任意一条边
理由很简单:从
但是一般图里可能出现
二分图的作用就在这里:二分图等价于“所有环长度为偶数”,也等价于“从固定根出发的最短路距离奇偶性给出一个合法二分划分”。因此对任意边
结合上一段的
这句话才是整题的地基:每条边一定连接相邻层,不会出现同层干扰。
2. 染色策略:到 1 最短距离模三
先手做一次宽度优先搜索求出所有
由上面的引理,
也就是说,站在
3. 后手的策略:先反推自己处在哪一层模三,再选让距离下降的那一色
如果后手在某一步看到邻居里同时出现两种颜色,那么缺失的那一种颜色就是自己当前点的颜色。因为邻居只可能是前驱色和后继色,两种都出现时,第三种必然对应
于是有三种确定情况:
- 邻居出现
r与b,缺g,说明自己是g,要走向更近的一层,也就是走向r - 邻居出现
r与g,缺b,说明自己是b,要走向g - 邻居出现
g与b,缺r,说明自己是r,要走向b
剩下是“邻居只有一种颜色”的情况。就随便选一个点即可,因为这些邻居的距离是一样的,你的距离也只可能从这些邻居上转移过来。
AC代码
AC
https://codeforces.com/contest/2179/submission/355080390
::::info[代码]
/**
* Problem: F. Blackslex and Another RGB Walking
* Contest: Codeforces Round 1071 (Div. 3)
* Judge: Codeforces
* URL: https://codeforces.com/contest/2179/problem/F
* Created: 2025-12-25 15:05:02
* Author: Gospel_rock
*/
#include <bits/stdc++.h>
#include <ranges>
#define all(vec) vec.begin(),vec.end()
#define lson(o) (o<<1)
#define rson(o) (o<<1|1)
#define SZ(a) ((long long) a.size())
#define debug(var) cerr << #var <<":"<<var<<"\n";
#define cend cerr<<"\n-----------\n"
#define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long;
using ull = unsigned long long;
using DB = double;
using LD = long double;
// using i128 = __int128;
using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1;
static constexpr ll mod = 998244353; // (ll)1e9+7;
static constexpr double eps = 1e-8;
const double pi = acos(-1.0);
ll lT;
/*
*
*/
void SolveFir() {
ll N,M;
cin>>N>>M;
vector<vector<ll>> g(N+2);
for (int i=1;i<=M;++i) {
ll u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
queue<pair<ll,ll>> q;
q.push({1,0});
vector<char> vis(N+2);
vector<ll> vec_dis(N+2);
vis[1]=true;
while (!q.empty()) {
auto [u,dis]=q.front();
q.pop();
for (auto v:g[u]) {
if (vis[v]) continue;
vis[v]=true;
vec_dis[v]=dis+1;
q.push({v,dis+1});
}
}
for (int i=1;i<=N;++i) {
ll op=vec_dis[i]%3;
if (op==0) {
cout<<"r";
}else if (op==1) {
cout<<"g";
}else {
cout<<"b";
}
}
cout<<"\n";
}
void SolveSec() {
ll Q;
cin>>Q;
for (int _=1;_<=Q;++_) {
ll n;
cin>>n;
string s;
cin>>s;
int r_have=0,g_have=0,b_have=0;
ll r_pos=0,g_pos=0,b_pos=0;
for (int i=0;i<s.size();++i) {
if (s[i]=='r') {
r_have=1;
r_pos=i+1;
}else if (s[i]=='g'){
g_have=1;
g_pos=i+1;
}else {
b_have=1;
b_pos=i+1;
}
}
if (r_have+g_have+b_have==1) {
cout<<1<<"\n";
continue;
}
if (r_have+b_have==2) {
cout<<r_pos<<"\n";
continue;
}
if (r_have+g_have==2) {
cout<<g_pos<<"\n";
continue;
}
if (g_have+b_have==2) {
cout<<b_pos<<"\n";
continue;
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
string s;
cin>>s;
cin >> lT;
if (s=="first") {
while(lT--)
SolveFir();
}else {
while(lT--)
SolveSec();
}
return 0;
}
/*
AC
https://codeforces.com/contest/2179/submission/355080390
first
1
4 4
1 2
1 3
4 2
4 3
*/
::::