题解:CF2008D Sakurako's Hobby
CF2008D 题解
题面
题意
给定一个 01
串,和一个 1∼n 的排列 pi,称两个数 i,j 是互相到达的,当且仅当 i 可以通过若干次 i=pi 而变成 j,询问对于每个 i,可以到达多少个在字符串中的位置为 0
的点。
思路
看到题目很容易就想到图论,把 i 与 pi 连一条有向边,把题目转换成图上的问题。
首先,因为 pi 是一个 1∼n 的排列,所以一个数至多指向一个点,一个数也至多被一个点指向。
于是就可以想到,这个图一定是若干个环组成的,而且环与环之间没有边相连。
到了这里,思路就很清晰了,直接跑一遍 tarjan,每个点的答案就是在其所在的强联通分量的点的个数。
代码很板,非常好打。
代码
注:题目要求能到达的 0
的个数,但作者为了方便,所以给取反了,改成求能到达的 1
的个数。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
const int MN=2e5+5;
ll n,a[MN],c[MN],head[MN],tot,low[MN],num[MN],dfn,f[MN],sta[MN],top,scc[MN],cnt,val[MN];
char s[MN];
bool vis[MN];
struct edge{
ll nxt,to;
void clear(){nxt=to=0;}
}e[MN<<2];
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
void add(ll u, ll v){e[++tot].nxt=head[u];head[u]=tot;e[tot].to=v;}
void init(ll n){
for(int i=0; i<=tot; i++) e[i].clear();
for(int i=0; i<=n; i++) head[i]=low[i]=num[i]=sta[i]=scc[i]=val[i]=0;
top=dfn=cnt=tot=0;
}
void tarjan(ll u){
low[u]=num[u]=++dfn;sta[++top]=u;
for(int i=head[u]; i; i=e[i].nxt){
ll v=e[i].to;
if(!num[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!scc[v]) low[u]=min(low[u],num[v]);
}
if(low[u]==num[u]){
cnt++;
while(1){
ll v=sta[top--];
scc[v]=cnt;val[cnt]+=c[v];
if(u==v) break;
}
}
}
void solve(){
init(n);
n=read();
for(ll i=1; i<=n; i++){
a[i]=read();
add(i,a[i]);
}
cin>>s;
for(int i=0; i<n; i++) c[a[i+1]]=s[i]-'0';
for(int i=1; i<=n; i++) c[i]=c[i]^1;
for(int i=1; i<=n; i++) if(!num[i]) tarjan(i);
for(int i=1; i<=n; i++) f[i]=val[scc[i]];
for(int i=1; i<=n; i++) write(f[i]),putchar(' ');putchar('\n');
}
int main(){
ll T=read();while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现