[P8346] 「Wdoi-6」最澄澈的空与海 题解
aeiouaoeiu · · 题解
直接考虑是非常困难的,考虑找到一个薄弱环节。
发现度数为
考察一个留下来的连通块,若其点数为
证明:连通,其必然能够取出一颗生成树,考虑树上任意一个度数为
1 的叶子,其另一条连边一定与这颗生成树上的边构成一个大小\ge 2 的环。
二分图,得到的环是偶环,对环上的边进行黑白染色,可以得到两种方案:用黑边匹配或用白边匹配。
所以如果有剩余连通块,即删边过程中有点没有被匹配,要么无解要么多解。
时间复杂度:
2025.11.19 upd:修改了代码使其通过 hack,思路没有变动。
::::info[code]
#include<bits/stdc++.h>
#define pb emplace_back
using namespace std;
typedef long long ll;
const ll maxn=2000007,p=998244353,B=14;
ll n,m,deg[maxn],vis[maxn],q[maxn],h,t;
vector<ll> edge[maxn];
void bfs(void){
h=0,t=1;
for(int i=1;i<=2*n;i++)if(deg[i]==1) q[++h]=i;
for(ll u;h>=t;){
u=q[t],t++;
for(auto v:edge[u])if(!vis[v]){
vis[v]=vis[u]=1;
for(auto w:edge[v])if(!vis[w]){
deg[w]--;
if(deg[w]==1) q[++h]=w;
}
}
}
}
string solve(void){
bfs();
for(int i=1;i<=2*n;i++)if(!vis[i]) return "Merry";
return "Renko";
}
int main(void){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0);
ll T=1; cin>>T;
for(;T--;){
for(int i=1;i<=2*n;i++) deg[i]=vis[i]=0,edge[i].clear();
cin>>n>>m;
for(int i=1,u,v;i<=m;i++){
cin>>u>>v,edge[u].pb(v+n),edge[v+n].pb(u);
deg[u]++,deg[v+n]++;
}
cout<<solve()<<"\n";
}
return 0;
}
::::