AtCoder Beginner Contest 387
可算找到了tarjan板子
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define yes cout << "Yes" << endl
#define no cout << "No" << endl
#define pii pair<int,int>
#define ll long long
#define pb push_back
#define ft first
#define se second
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define int long long
int n,m;
const int p=998244353;
const int N=3000;
vector<int> G[N];
int dfn[N],low[N],stk[N],instk[N],scc[N];int cnt_scc;int tot=0;int tp=0;
vector<int>G1[N],E1[N];
int f[N][N],g[N][N];
void tarjan(int u)
{
dfn[u]=low[u]=++tot;
instk[u]=1,stk[++tp]=u;
for(auto v:G[u])
{
if(dfn[v]==0)
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instk[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u])
{
int now;
cnt_scc++;
do{
now=stk[tp--];
instk[now]=0;
scc[now]=cnt_scc;
}while(now!=u);
}
}
int ind[N];bool nood[N];
vector<int> topo;
void toposort(){
stack<int> s;topo.pb(0);
for(int i=1;i<=cnt_scc;i++){
if(!ind[i]){s.push(i);
// for(int j=1;j<=m;j++)f[i][j]=1;
// for(int j=1;j<=m;j++)g[i][j]=g[i][j-1]+f[i][j];
}
}
while(!s.empty()){
int t=s.top();s.pop();
topo.pb(t);
for(auto v:G1[t]){
if(--ind[v]==0)s.push(v);
}
}
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
int _;cin>>_;G[i].pb(_);nood[i]=1;
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++){
int u=i;u=scc[i];
for(auto v:G[i]){
v=scc[v];
if(u!=v){G1[u].pb(v);nood[u]=0;
E1[v].pb(u);ind[v]++;}
}
}
toposort();
for(int ii=1;ii<=cnt_scc;ii++){
int i=topo[ii];
for(int j=1;j<=m;j++){
f[i][j]=1;
}
for(auto v:E1[i]){
for(int j=1;j<=m;j++){
f[i][j]=(f[i][j]*g[v][j])%p;
}
}
for(int j=1;j<=m;j++)g[i][j]=(g[i][j-1]+f[i][j])%p;
// cout<<"geti"<<i<<"*";for(int j=1;j<=m;j++)cout<<f[i][j]<<" ";cout<<'\n';
}
int ans=1;
for(int i=1;i<=cnt_scc;i++){
if(nood[i])ans=(ans*g[i][m])%p;
}
cout<<ans<<'\n';
}
signed main(){
std::ios::sync_with_stdio(false);
int T=1;
while(T--){
solve();
}
}

浙公网安备 33010602011771号