Description
珂朵莉给了你一个无向图,每次查询给ttt个点以及一个常数sss,求有多少个图中的点距离给出的那ttt个点中至少一个距离≤s\le s≤s
Input
第一行三个数表示n,m,qn,m,qn,m,q
之后mmm行每行两个数u,vu,vu,v表示有一条边位于uuu和vvv两个点之间
之后 2q2 q2q 行表示询问
每次询问先输入两个数t,st,st,s
之后一行ttt个数,表示ttt个特殊点
(1≤n,m,q≤5000,∑t≤5⋅105,s≤109)(1\le n,m,q\le 5000,\sum t\le 5\cdot 10^5,s\le 10^9)(1≤n,m,q≤5000,∑t≤5⋅105,s≤109)
Output
qqq行,每行一个数表示答案
Sample Input
5 6 6
2 3
1 3
2 5
1 3
3 2
2 5
1 1
3
1 1
1
1 4
1
1 2
5
1 4
1
1 4
5
Sample Output
3
2
4
3
4
4
Solution
每次以所给ttt个点为起点bfsbfsbfs整张图即可,时间复杂度O((n+m)q)O((n+m)q)O((n+m)q)
Code
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int maxn=5005;
int n,m,q,dis[maxn],vis[maxn];
vector<int>g[maxn];
int main()
{
scanf("%d%d%d",&n,&m,&q);
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v),g[v].push_back(u);
}
while(q--)
{
int t,s;
scanf("%d%d",&t,&s);
for(int i=1;i<=n;i++)dis[i]=s+1,vis[i]=0;
queue<int>que;
for(int i=1;i<=t;i++)
{
int u;
scanf("%d",&u);
que.push(u);
dis[u]=0;
vis[u]=1;
}
while(!que.empty())
{
int u=que.front();
que.pop();
if(dis[u]==s)break;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(vis[v])continue;
vis[v]=1,dis[v]=dis[u]+1,que.push(v);
}
}
int res=0;
for(int i=1;i<=n;i++)
if(dis[i]>s)res++;
printf("%d\n",n-res);
}
return 0;
}