思路:
x − > f ( x ) x->f(x) x−>f(x)建图,看每个环的平均值是否相同。
代码:
const int maxn=2e5+7,maxm=2e5+7;
ll n;
ll h[maxn],e[maxm],ne[maxm],idx,f[maxn],w[maxn];
ll dfn[maxn],low[maxn],timetamp,belong[maxn];
stack<int>stk;
bool st[maxn];
ll scc_cnt;
void init(){
memset(h,-1,sizeof h);
memset(w,0,sizeof w);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(belong,0,sizeof belong);
memset(st,0,sizeof st);
idx=scc_cnt=timetamp=0;
}
void add(ll a,ll b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int u){
dfn[u]=low[u]=++timetamp;
stk.push(u);st[u]=1;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(!dfn[j]){
tarjan(j);
low[u]=min(low[u],low[j]);
}
else if(st[j]) low[u]=min(low[u],dfn[j]);
}
if(dfn[u]==low[u]){
++scc_cnt;
int y;
do{
y=stk.top();
stk.pop();
belong[y]=scc_cnt;
st[y]=0;
}while(y!=u);
}
}
vector<int>g[maxn];
int main(){
int _=read;
while(_--){
init();
n=read;
rep(i,1,n){
f[i]=read;
add(i,f[i]);
g[i].clear();
}
rep(i,1,n) if(!dfn[i]) tarjan(i);
rep(i,1,n)
w[belong[i]]+=f[i],g[belong[i]].push_back(i);
ll resp=-1,resq=-1,flag=1;
vector<int>v;
rep(i,1,scc_cnt){
if(g[i].size()==1){
if(g[i][0]==f[g[i][0]]){
if(resp==-1){
resp=1,resq=w[i];
}
else{
if(resp*w[i]!=resq*1){
flag=0;break;
}
}
}
}
else if(g[i].size()>1) {
if(resp==-1){
resp=g[i].size(),resq=w[i];
}
else{
if(resp*w[i]!=resq*g[i].size()){
flag=0;break;
}
}
}
}
if(flag) puts("YES");
else puts("NO");
}
return 0;
}