csp2022 T3 的条件充要性证明

必要性显然。

当且仅当只有一个从该据点出发的虫洞可用时

考虑我的暴力做法是缩点成若干 DAG,然后对强连通分量点数大于等于 2 的权值赋为 1,其他赋为 0,然后建反图跑拓扑,看看是不是每个点都能被传递到权值 1。

然后你这样做显然很复杂,根据经验,你觉得不够优美,并且猜测没有人会优化!显然是你性质/条件没找对。

考虑先判完充要后,细究我们缩点后的 DAG。

建议自己画个图。

  • 入度为 0 的点的强连通分量大小一定为 1。
    证明:考虑大于等于 1 的情况成环,那么已经满足环内每个点出度为 1 了,结果还得多一条出来,直接被必要条件判掉了。

  • 强连通分量出度为 1 强连通分量大小为 1
    证明:类上条结论证即可。若有出边,显然被判掉。

  • 只有出度为 0 的点的权值为 1
    证明:显然出度为 0,没被判掉,所以一定成环。

然后你想 DAG 只有出度为 0 的点权值为 1,接下来建反图,显然以这些点为源点,每个点都能跑得到。若存在孤立强连通分量的话也显然。

哈哈,你这个结论假如猜对的话,随便过 T3。

考虑条件不好做,且等价于边为 n,每个点的度数为奇数。

考虑奇数想到异或,然后你随便做一下就好了。

也就是说,对于一条边 (x,y),就对全局答案异或上 vxvx 为给 x 赋的随机权值。

#include <bits/stdc++.h> //#define int long long #define pb push_back using namespace std; const int N=(int)(5e5+5); mt19937 RAND(time(0)^1919810); int n,m,d[N],v[N],f[N],sum[N],del[N],in[N]; signed main() { cin.tie(0); ios::sync_with_stdio(false); cin>>n>>m; int bian=m,val=0,Lim=0; for(int i=1;i<=n;i++) v[i]=RAND(),Lim^=v[i]; for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; ++d[x]; val^=v[x]; ++in[y]; sum[y]^=v[x]; } int q; cin>>q; while(q--) { int op; cin>>op; if(op==1) { int x,y; cin>>x>>y; --bian; f[y]^=v[x]; val^=v[x]; ++del[y]; } else if(op==2) { int x; cin>>x; int qwq=sum[x]^f[x]; //未 val^=qwq; f[x]=sum[x]; int re=in[x]-del[x]; bian-=re; del[x]=in[x]; } else if(op==3) { int x,y; cin>>x>>y; ++bian; f[y]^=v[x]; val^=v[x]; --del[y]; } else if(op==4) { int x; cin>>x; bian+=del[x]; val^=f[x]; f[x]=0; del[x]=0; } if(val==Lim&&bian==n) cout<<"YES\n"; else cout<<"NO\n"; } return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16845733.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示