SRM系列的博客主要得益于 Jiry_2 这篇博客的启发,但由于他只给出了简洁题解,我决定自己写一波。由于SRM高分题有一定的难度,这个系列我就不提示了。
进入正题:
我们先考虑一个简单的版本。 如果只有一个入口,那么有几种情况呢?
这其实就是给定元素让你求有多少种大根堆是吧! 记录
di
表示以
i
为根的堆有几种情况,每次重标号,然后组合数搞一搞即可。
现在我们考虑有两个入口的情况。 你会发现其实对于某一些点而言, 一个入口两个入口都无所谓,不管从哪个入口进来都必须从自己的父亲那条边到自己。只有在
回想刚才处理一个入口的情况, 我们先确定根放最大的,然后逐个分给各个儿子。现在我们有两个入口了,我们不能确定根放在哪里,但是肯定只能放在左端点和右端点,于是我们想到用区间 dp . 分别枚举放在左右端点,转移即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3100;
const int modu = 1e9+7;
int c[maxn][maxn];
class TwoEntrances
{
int n , s1 , s2 , pre[maxn] , inLine[maxn] , Size[maxn] , iS[maxn][maxn];
vector<int> p , g[maxn];
public:
void dfs(int x)
{
if(x == s2)
{
inLine[x] = 1; p.push_back(x);
for(;;)
{
x = pre[x];
inLine[x] = 1;
p.push_back(x);
if(x == s1) break;
}
return;
}
for(int i=0;i<g[x].size();i++)
{
int t = g[x][i];
if(t == pre[x]) continue;
pre[t] = x;
dfs(t);
}
}
int d[maxn] , f[maxn][maxn];
void dfs(int x , int fa)
{
Size[x] = 1;
for(int i=0;i<g[x].size();i++)
{
int t = g[x][i];
if(t == fa || inLine[t]) continue;
dfs(t, x);
Size[x] += Size[t];
}
int cnt = Size[x] - 1 , &res = d[x] = 1;
for(int i=0;i<g[x].size();i++)
{
int t = g[x][i];
if(t == fa || inLine[t]) continue;
res = (((1LL*res*d[t])%modu)*1LL*c[cnt][Size[t]]) % modu;
cnt -= Size[t];
}
}
int count(vector <int> a, vector <int> b, int s1, int s2)
{
++s1; ++s2;
this->s1 = s1; this->s2 = s2;
n = a.size()+1;
for(int i=0;i<=n;i++)
{
c[i][0] = c[i][i] = 1;
for(int j=1;j<i;j++) c[i][j] = (c[i-1][j]+c[i-1][j-1]) % modu;
}
for(int i=0,x,y;i<n-1;i++)
{
x = a[i]+1; y = b[i]+1;
g[x].push_back(y);
g[y].push_back(x);
}
pre[s1] = 0;
dfs(s1);
for(int i=0;i<p.size();i++) dfs(p[i], 0);
for(int i=0;i<p.size();i++) for(int l=0,r;l+i<p.size();l++)
{
r = l+i;
if(l == r) f[l][r] = d[p[l]] , iS[l][r] = Size[p[l]];
else
{
iS[l][r] = iS[l][r-1] + Size[p[r]];
f[l][r] = (((1LL*d[p[l]]*c[iS[l][r]-1][iS[l+1][r]])%modu)*f[l+1][r])%modu
+(((1LL*d[p[r]]*c[iS[l][r]-1][iS[l][r-1]])%modu)*f[l][r-1])%modu;
f[l][r] %= modu;
}
}
return f[0][p.size()-1];
}
};
TwoEntrances solver;
int main(int argc, char *argv[]) {
int n;
cin>>n;
vector<int> a , b;
for(int i=1,x;i<=n;i++) cin>>x , a.push_back(x);
for(int i=1,x;i<=n;i++) cin>>x , b.push_back(x);
int s1 , s2;
cin>>s1>>s2;
cout<<solver.count(a , b , s1 , s2)<<endl;
return 0;
}