https://acm.hdu.edu.cn/showproblem.php?pid=7050
题意相当于问n个点n条边的有向图(可能有自环),是否所有的环的平均值相等
用tarjan找环效果不甚理想,还是std的拓扑排序妙
#include<bits/stdc++.h> using namespace std; #define N 100001 int to[N]; int dfn[N],low[N],id; int st[N],top; bool in[N]; double last,now; int sum; const double eps=1e-8; bool equal(double a,double b) { return fabs(a-b)<eps; } void tarjan(int u) { low[u]=dfn[u]=++id; st[++top]=u; in[u]=true; int t=to[u]; if(!dfn[t]) { tarjan(t); low[u]=min(low[u],low[t]); } else if(in[t]) low[u]=min(low[u],dfn[t]); if(low[u]==dfn[u]) { if(st[top]==u) { in[u]=false; top--; return; } while(st[top]!=u) { in[st[top]]=false; now+=st[top--]; sum++; } now+=st[top--]; sum++; in[u]=false; } } int main() { //freopen("input.txt","r",stdin); //freopen("my.txt","w",stdout); int T,n; int self,who; bool tag; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;++i) { dfn[i]=0; in[i]=false; } id=0; self=0; for(int i=1;i<=n;++i) { scanf("%d",&to[i]); if(to[i]==i) { ++self; who=i; } } if(self>1) { printf("NO\n"); continue; } last=-1; if(self==1) { last=who; dfn[who]=1; } tag=true; for(int i=1;i<=n && tag;++i) { if(dfn[i]) continue; now=0; top=sum=0; tarjan(i); if(!sum) continue; now/=sum; if(!equal(now,last) && !equal(last,-1)) tag=false; last=now; } if(tag) printf("YES\n"); else printf("NO\n"); } }View Code
#include <stdio.h> #include <queue> #define MN 100000 typedef long long ll; int n,a[MN+5],din[MN+5]; void solve(){ scanf("%d",&n); for(int i=1;i<=n;i++){ din[i] = 0; } for(int i=1;i<=n;i++){ scanf("%d",&a[i]); din[a[i]]++; } std::queue<int> Q; for(int i=1;i<=n;i++){ if(din[i]==0) Q.push(i); } while(!Q.empty()){ int u = Q.front(); Q.pop(); din[a[u]]--; if(din[a[u]]==0){ Q.push(a[u]); } } ll p=-1,q=-1; for(int i=1;i<=n;i++){ if(din[i]==0) continue; ll tp=0,tq=0; for(;din[i];i=a[i]){ tp += i; tq++; din[i] = 0; } if(p==-1){ p = tp; q = tq; }else{ if(p*tq!=q*tp){ puts("NO"); return; } } } puts("YES"); return; } int main(){ int T; scanf("%d",&T); while(T--) solve(); }View Code