luogu P5676 [GZOI2017]小z玩游戏 |Tarjan+技巧优化建图
Posted naruto-mzx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P5676 [GZOI2017]小z玩游戏 |Tarjan+技巧优化建图相关的知识,希望对你有一定的参考价值。
题目描述
小 z 很无聊。
小 z 要玩游戏。
小 z 有NNN个新游戏,第iii个游戏看上去的有趣程度为wiw_iwi?。
小 z 很挑,他只会玩看上去的有趣程度是自己兴奋程度整数倍的游戏。
由于游戏实际上有好玩的也有不好玩的,玩完第iii个游戏后,小 z 的兴奋程度会变为eie_iei?。
已知小 z 初始兴奋程度为111,请问小 z 有多少个游戏可能会玩两次?
输入格式
第一行一个正整数TTT,表示测试数据组数,最多101010组。
对于每组测试数据:
第一行一个正整数NNN,表示游戏的个数。
第二行NNN个正整数,第iii个数wiw_iwi?,表示第iii个游戏看上去的有趣程度为wiw_iwi?。
第三行NNN个正整数,第iii个数eie_iei?,表示小 z 玩完第iii个游戏后,小 z 的兴奋程度会变为eie_iei?。
输出格式
共TTT行。
每行一个正整数,表示对应测试数据,小 z 可能会玩两次的游戏数量。
一个数组初始化问题,改了我一天..
建虚点,模拟找倍数过程
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e5+1,M=80*N;
int nxt[M],head[N],go[M],tot;
inline void add(int u,int v){
nxt[++tot]=head[u];head[u]=tot;go[tot]=v;
}
int n;
bool vis[N];
int dfn[N],low[N],co[N],st[N],top,col,num;
inline void clear(){
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
memset(nxt,0,sizeof(nxt));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(co,0,sizeof(co));
col=0; num=0; tot=0;
}
void Tarjan(int u){
st[++top]=u;
dfn[u]=low[u]=++num;
for(int i=head[u];i;i=nxt[i]){
int v=go[i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(!co[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
co[u]=++col;
int siz=1;
while(st[top]!=u){
co[st[top]]=col;
vis[st[top]]=1;
siz++;
top--;
}
if(siz>1)vis[u]=1;
--top;
}
}
signed main(){
int T; cin>>T;
while(T--){
scanf("%d",&n);
int Max=0;
for(int i=1,x;i<=n;i++)scanf("%d",&x),add(n+x,i),Max=max(Max,x);
for(int i=1,x;i<=n;i++)scanf("%d",&x),add(i,n+x);
for(int i=1;i<=Max;i++)for(int j=2;j*i<=Max;j++)
add(n+i,n+i*j);
for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i);
int ans=0;
for(int i=1;i<=n;i++)if(vis[i])ans++;
printf("%d
",ans);
clear();
}
}
以上是关于luogu P5676 [GZOI2017]小z玩游戏 |Tarjan+技巧优化建图的主要内容,如果未能解决你的问题,请参考以下文章
Luogu P5304 [GXOI/GZOI2019]旅行者
Luogu P5304 [GXOI/GZOI2019]旅行者
luogu P5300 [GXOI/GZOI2019]与或和