CF--新年场--D
关键
这种有因果关系的,确实是用图论,但是我是想用topo
最后连边失败
这里是分成多个连通块,每个连通块的点数必须和边数相同
而且如果已经算过贡献,就不在重复计算了
代码
//每一个环的点数和边数都必须要相同 //如果这个环已经乘过贡献了,那就不在次计算贡献,直接标记为1就可以了 //用并查集来统计连通块的点和边 //两个点一条边就可以了 #include <bits/stdc++.h> using namespace std; #define int long long const int M=1e5+5; const int mod=998244353; int a[M],b[M];; int siz[M],cnt[M]; bool st[M]; int fa[M]; int find(int x) { return x==fa[x]?fa[x]:fa[x]=find(fa[x]); } signed main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int TT;cin>>TT; while(TT--) { int n;cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++)cin>>b[i]; for(int i=1;i<=n;i++)cnt[i]=st[i]=0,fa[i]=i,siz[i]=1; int ans=1; for(int i=1;i<=n;i++) { if(a[i]==b[i])st[a[i]]=1,ans=ans*n%mod;//自环的环,标记已成乘过了 cnt[a[i]]++; fa[find(a[i])]=find(b[i]); } for(int i=1;i<=n;i++) if(find(i)!=i)cnt[find(i)]+=cnt[i],st[find(i)]|=st[i],siz[find(i)]++; //吧孩子的状态进行统计 for(int i=1;i<=n;i++) if(find(i)==i) { if(cnt[i]!=siz[i])ans=0;//点数和边数不相同 if(st[i]==0)ans=ans*2%mod; } cout<<ans<<endl; } return 0; } //当时是想着有些点是已经连了,然后把已经连过的相关的点又进行连接,模拟起来确实有些复杂 //正确性也不得而知,虽然感觉思路没啥问题 //但是还是需要简化模拟吧
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现