在x处bfs一遍,随后用cnt[5005]存入拥有i距离的点个数。期间维护max_point(距离x的最远距离)剪枝。
预处理二维01背包节省时间
状态方程如下:
i表示选择的距离,j表示当前已经选择的方案数
dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*cnt[i]
#include <iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define pb push_back
#define vt vector
using ll =long long;
#define qe queue
#define p push
const ll mod=1e9+7;
vt <int> op[1000005];
int cnt[5005];
int n,m,q,x;
ll max_point;
void bfs(int i,qe<pair<int,int>> &qp){
vt <bool> vst(n+1,false);
qp.push({i,0});
vst[i]=true;
while(!qp.empty()){
int now=qp.front().first;
int res=qp.front().second;
if(max_point<res) max_point=res;
qp.pop();
for(int j:op[now]){
if(vst[j]==false){
vst[j]=true;
qp.p({j,res+1});
cnt[res+1]++;
}
}
}
return ;
}
int main() {
cin>>n>>m>>q>>x;
vt <bool> vst(n+1,false);
for(int i=0;i<m;i++){
int u,v;
cin>>u>>v;
op[u].pb(v);
op[v].pb(u);
}
qe<pair<int,int>> qp;
bfs(x,qp);
vt<vt<ll>> dp(5005,vt<ll>(5005,0));
dp[0][0]=1;
for(int i=1;i<=max_point;i++){
dp[i][0]=1;/*令每一层的dp[i][1]能正确加上cnt[i]*/
for(int j=1;j<=i;j++){
dp[i][j]=(dp[i-1][j]%mod+dp[i-1][j-1]*cnt[i]%mod)%mod;
}
}
for(int i=0;i<q;i++){
int k;
cin>>k;
if(k>max_point) cout<<0<<endl;
else cout<<dp[max_point][k]<<endl;
}
}

京公网安备 11010502036488号