题解:P17406 【MX-X31-T2】「FAOI-R14」警察抓小偷
什么数数+DS 场。
显然原图为内向基环树,考虑一个叶子,显然初始时上面一定要有一个警察。
足够长时间后,小偷一定在环上,如果环上有一个点没有警察,小偷初始时一定可以选择一个位置使自己一直不被抓住。因此环上的每个点都至少要有一个警察。
一个简单的做法是:直接用倍增求出每个点顺着出边走
代价为
::::success[赛时代码]
#include<bits/stdc++.h>
#define N 1000005
#define mod 998244353
using namespace std;
long long t,n,c,s,r,m,i,j,d[N],w[N],a[N][21];
bool f[N];
vector<long long>v[N];
int main(){
cin.tie(0)->sync_with_stdio(0);
cin>>t;
while(t--){
cin>>n;
c=0;
for(i=1;i<=n;i++){
d[i]=f[i]=0;
v[i].clear();
}
for(i=1;i<=n;i++)cin>>w[i];
for(i=1;i<=n;i++){
cin>>a[i][0];
d[a[i][0]]++;
}
for(i=1;i<=20;i++)for(j=1;j<=n;j++)a[j][i]=a[a[j][i-1]][i-1];
for(i=1;i<=n;i++){
if(d[i])v[a[i][20]].push_back(w[i]);
else{
c+=w[i];
f[a[i][20]]=1;
}
}
for(r=i=1;i<=n;i++){
if(!v[i].empty()){
m=LLONG_MAX;
for(auto j:v[i])m=min(m,j);
if(!f[i])c+=m;
if(m){
if(f[i])continue;
s=0;
for(auto j:v[i])if(j==m)s++;
r=r*s%mod;
}else{
s=1;
for(auto j:v[i])if(!j)s=s*2%mod;
r=r*(s+mod-!f[i])%mod;
}
}
}
cout<<c<<' '<<r<<'\n';
}
}
::::