CF711D 【Directed Roads】
这是一场比赛的 T4T4 ,身为蒟蒻的我当然没有想出来。
后来对基环树有了一点了解之后就来肝这道题。
首先对于一条边,只有两种情况
1.在环上,那么这个环只有全部正向或全部反向才可以成立,而总方案数显然是 2m ,其中 mm 是环上的边数,所以方案数就是 2m-2
2.不在环上,那么这种边就可以随意取,也就是2w−∑m ,也就是所有的边数减去在环上的边。
先用拓扑排序找出所有的环,再用乘法原理统计就是了
注意的点
1.int 和bool的区别
2.ans初始化为1
3.拓扑排序注意记录深度
#include<bits/stdc++.h> #define isdigit(a) (a>=48&&a<=57) const int N=2e5+5; const int mod=1e9+7; using namespace std; int n,a,head[N],tot; struct node{int to,next;}e[N]; void add(int u,int v){e[++tot].to=v;e[tot].next=head[u];head[u]=tot;} inline int read(){ char c=getchar();int fh=0; while(!isdigit(c))c=getchar(); while(isdigit(c))fh=(fh<<1)+(fh<<3)+(c^48),c=getchar(); return fh; } int hh,m,po[N]={1},ans=1; int vis[N],dfn[N]; void dfs(int u,int d){ dfn[u]=d;vis[u]=1; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(!vis[v])dfs(v,d+1);//还没访问过继续 else if(vis[v]==1)hh=dfn[u]-dfn[v]+1,ans=(1ll*ans*(po[hh]-2+mod))%mod,m-=hh;//统计环上的边数,更新答案,边数减去在环上的边 } vis[u]=2;//已访问过,且已经全部访问完 } int main(){ m=n=read(); for(int i=1;i<=n;++i)po[i]=(po[i-1]*2ll)%mod;//预处理2的次幂 for(int i=1;i<=n;i++)a=read(),add(i,a);//添加单向边 for(int i=1;i<=n;++i) if(!vis[i]){ hh=0; dfs(i,0);//拓扑排序 } ans=(1ll*ans*po[m])%mod;//统计不是环上的边 cout<<ans<<endl; }
【推荐】AI 的力量,开发者的翅膀:欢迎使用 AI 原生开发工具 TRAE
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C#性能优化:为何 x * Math.Sqrt(x) 远胜 Math.Pow(x, 1.5)
· 本可避免的P1事故:Nginx变更导致网关请求均响应400
· 还在手写JSON调教大模型?.NET 9有新玩法
· 复杂业务系统线上问题排查过程
· 通过抓包,深入揭秘MCP协议底层通信
· AI 的力量,开发者的翅膀:欢迎使用字节旗下的 AI 原生开发工具 TRAE
· C#性能优化:为何 x * Math.Sqrt(x) 远胜 Math.Pow(x, 1.5)
· 「闲聊文」准大三的我,思前想后还是不搞java了
· 千万级的大表如何新增字段?
· 《HelloGitHub》第 112 期