[GCJ 2022 #3] Mascot Maze 题解
感觉是挺好的 trick。
这题是图的点染色问题的特殊情况,注意到原图上每个点的出度都最多为
证明:其中
每次删掉一个度数
使用队列进行 BFS 模拟删掉度数
放代码:
#include<bits/stdc++.h>
using namespace std;
const string S="ACDEHIJKMORST";
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int tt; cin>>tt;
for(int t=1;t<=tt;t++){
int n; cin>>n;
vector<int> l(n),r(n);
for(auto &i:l)cin>>i,i--;
for(auto &i:r)cin>>i,i--;
vector<vector<int> > g(n);
bool f=true;
for(int u=0;u<n&&f;u++)
for(int i:{l[u],r[u]}){
g[u].emplace_back(i);
g[i].emplace_back(u);
for(int j:{l[i],r[i]}){
if(u==j){f=false; break;}
g[u].emplace_back(j);
g[j].emplace_back(u);
}
} // 建出“矛盾图”
cout<<"Case #"<<t<<": ";
if(!f){cout<<"IMPOSSIBLE\n"; continue;}
vector<int> d(n),v,c(n,-1);
vector<bool> b(n);
queue<int> q;
for(int u=0;u<n;u++){
sort(g[u].begin(),g[u].end());
g[u].erase(unique(g[u].begin(),g[u].end()),g[u].end());
if((d[u]=g[u].size())<=12)b[u]=true,q.emplace(u);
} // 对边去重,并加入初始时度数不大于 12 的点
while(!q.empty()){
int u=q.front(); q.pop();
v.emplace_back(u);
for(int i:g[u])
if(--d[i]<=12&&!b[i])b[i]=true,q.emplace(i);
} // 执行一个类似拓扑排序的过程
reverse(v.begin(),v.end());
for(int u:v){
vector<bool> b(13);
for(int i:g[u])
if(~c[i])b[c[i]]=true;
for(int i=0;i<13;i++)
if(!b[i]){c[u]=i; break;}
} // 倒推回来染色
for(int i:c)cout<<S[i];
cout<<'\n';
}
return 0;
}