在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;
    }
}