D. Koxia and Game
tilian
很容易发现就是我们要让每个数字都double choice一次才能得到答案
比如第一个样例
我们发现1 1 已经double choice一次过了 所以我们该点可以搞任何的数字就是n种选择
我们发现第二个和第三个就像一个环一样 确定了一个其他所有都被确定了就只有两种情况
而且我们会发现有些像链一样 (我们把a[i]和b[i]用边连起来)
1 2 3
2 3 4
这种是没有解的 但是他要是挂在一个环上的话就有解了
1 2 3 4
2 3 4 4
所以我们会发现一个连通块必须有几个点 就要有几条边
这样我们就记录一下 谁是自环 每个连通块有几个点几个边即可
int n,p[N],v[N],e[N],loop[N],a[N],b[N];
int find(int x){
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
void merge(int x,int y){
int pa=find(x),pb=find(y);
e[pa]+=e[pb];
v[pa]+=v[pb];
p[pb]=p[pa];
loop[pa]|=loop[pb];
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++){
loop[i]=e[i]=0;
p[i]=i;
v[i]=1;
}
for(int i=1;i<=n;i++){
int pa=find(a[i]),pb=find(b[i]);
if(pa!=pb)merge(pa,pb);
e[find(a[i])]++;
if(a[i]==b[i])loop[pa]=1;
}
vector<int>mp(n+1);
int ans=1;
for(int i=1;i<=n;i++){
int x=find(i);
if(mp[x])continue;
if(e[x]!=v[x])ans=0;
if(loop[x])(ans*=n)%=mod;
else (ans*=2)%=mod;
mp[x]++;
}
cout<<ans<<endl;
}
标签:Good,int,我们,pb,NEAR,pa,Bye,find,loop
From: https://www.cnblogs.com/ycllz/p/17016930.html