小兔要和小鹿一起散步。
现在小兔已经选好了她的约会场所,并将它划分为 n 块区域。他们游览完i号区域会走向第vi号区域。
小兔想要在区域内种上一些小鹿喜欢的花,共有 m 种。为了使散步时不乏味,第 vi号区域的花的种类不能和第 i 号区域一样。
热爱计算的小兔想求有多少种种花方案满足上述条件,她一秒钟就求出来了,但她想D您,所以也叫您解决这个问题。
因为结果可能很大,所以只要输出方案数除以 10007 的余数。
输入
第一行包含两个正整数 n,m,中间由一个空格隔开,表示区域个数和小鹿喜欢的花的种类数。
接下来 n 个数 vi,表示游览完i号区域会走向第 vi号区域。
输出
仅一行,一个正整数,表示方案数除以 10007 的余数。
样例输入 Copy
2 3
2 1
样例输出 Copy
6
代码如下。
这个题,每个点都只有一个出去的点,即出度都为1,入度不确定
所以,每个连通块都存在一个环,在环上的点,爆搜找答案
不在环上的,对答案的贡献只有m-1
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
const double eqs=1e-7;
int to[maxn],vis[maxn],diss[maxn];
const ll mod=10007;
int bb,n;
ll m,ans=1;
ll dfs2(ll xt,ll bt,int i)
{
diss[i]=1;
if(diss[to[i]]) return bt;
ll xxt=bt,bbt=xt*(m-1)%mod+bt*(m-2)%mod;
return dfs2(xxt,bbt%mod,to[i]);
}
void dfs1(int i)
{
if(vis[to[i]]==bb)
{
ans=ans*dfs2(1,0,i)%mod*m%mod;
diss[i]=2;
vis[i]=bb;
return ;
}
vis[i]=bb;
if(!vis[to[i]]) dfs1(to[i]);
}
int main()
{
scanf("%d %lld",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&to[i]);
}
for(int i=1;i<=n;i++)
{
bb=i;
if(!vis[i])
{
dfs1(i);
}
if(diss[i]==0) ans=ans*(m-1)%mod;
}
printf("%lld\n",ans);
return 0;
}