Atcoder题解:Agc018_f
首先观察这个奇怪的子树为
看不出来性质,润了。
我们不如直接把
第一,我们对着样例构造一下,发现似乎有解的样例都有
这就提示我们猜用
然后,我们发现,当前点是偶数当且仅当自己在两棵树的儿子数量都是奇数,因为每一个儿子的
至于剩下的还会无解吗?不会了。为什么?构造出来不就是了。
现在我们来讲怎么构造。
我们把
然后,我们在两棵树的对应点之间连边,从 A 指向 B 或者从 B 指向 A,注意我们只去构造
这里看起来就有些怪,因为这样在 A 树点上的贡献和 B 树点的贡献就不一样了。但是我们发现它正好是相反数,那么我们直接把 B 树的点权全部取反,也不会有任何影响。(因为答案要求的是
然后我们发现,只要我们重新定向这个图,让每个子树的度数和都是
然后我们发现,这是一张半无向欧拉图。除了两个根节点以外,所有的点的度数都是偶数(因为我们给每个是奇数的都补了一条边),而根节点是奇数,所以就可以通过
感觉这个题有点厉害,其实从头到尾好多结论都是边猜边做,只是抱着一个“一定能找到答案”的信念去构造,最后居然真的构造出来了。
代码难度不高,但是我不会无向图欧拉回路,去背了个 dfs 插入环的板子,暂时还不会证明这个算法,学了个会证的 Fluery,居然还要动态图优化到
int n,fa[100005],fb[100005],ra,rb,res[100005],cnt;
int to[600005],used[300005];
vt<int>va[100005],vb[100005];
vt<pii>vv[200005];
inline void dfs(int x){
while(vv[x].size()){
int y=vv[x].back().first,z=vv[x].back().second;
vv[x].pop_back();
if(!used[z]){
used[z]=1;
if(to[z]){
if(y>x)res[to[z]]=1;
else res[to[z]]=-1;
}
dfs(y);
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
rp(i,n){
cin>>fa[i];
if(fa[i]==-1)ra=i;
else va[fa[i]].pb(i);
}
rp(i,n){
cin>>fb[i];
if(fb[i]==-1)rb=i;
else vb[fb[i]].pb(i);
}
rp(i,n)if((va[i].size()&1)!=(vb[i].size()&1)){
cout<<"IMPOSSIBLE"<<endl;
return 0;
}
rp(i,n)if(!(va[i].size()&1)){
++cnt;
vv[i].pb({i+n,cnt});
vv[i+n].pb({i,cnt});
to[cnt]=i;
}
rp(i,n)if(fa[i]!=-1){
++cnt;
vv[i].pb({fa[i],cnt});
vv[fa[i]].pb({i,cnt});
}
rp(i,n)if(fb[i]!=-1){
++cnt;
vv[i+n].pb({fb[i]+n,cnt});
vv[fb[i]+n].pb({i+n,cnt});
}
++cnt;
vv[ra].pb({rb+n,cnt});
vv[rb+n].pb({ra,cnt});
dfs(1);
cout<<"POSSIBLE"<<endl;
rp(i,n)cout<<res[i]<<" ";
cout<<endl;
return 0;
}
//Crayan_r
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!