题目大意:
有一个n个点的无向图,有m次查询,每次查询给出一些(xi,yi)
令dist(x,y)表示x和y点在图中最短距离,dist(x,x)=0,如果x,y不连通则dist(x,y) = inf
每次查询图中有多少个点v与至少一个这次询问给出的(xi,yi)满足dist(v,xi)<=yi
n
<
=
1000
,
m
<
=
100000
,
q
<
=
100000
n <= 1000 , m <= 100000 , q <= 100000
n<=1000,m<=100000,q<=100000
所有查询的限制的个数的和
<
=
2100000
<= 2100000
<=2100000
分析:
令
d
p
i
,
j
dp_{i,j}
dpi,j表示到点
i
i
i距离为
j
j
j的点有多少个,用
b
i
t
s
e
t
bitset
bitset存
因为是最短距离,所以先到肯定是最优,
n
n
n遍
b
f
s
bfs
bfs,
O
(
n
∗
m
)
O(n*m)
O(n∗m)可以处理出来
然后我们发现对于每个询问的结果就是所有的
d
p
x
,
y
dp_{x,y}
dpx,y的
o
r
or
or和
好像用数组弄邻接表会T炸,还改用成vector
代码:
#include <iostream>
#include <cstdio>
#include <bitset>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#define N 100005
#define M 1005
using namespace std;
int dis[M][M], ls[M], n, m, q, cnt;
bitset <M> dp[M][M];
vector <int> cdp[M];
queue <int> Q;
void bfs(int x)
{
while (Q.size()) Q.pop();
dis[x][x] = 0;
dp[x][0][x] = 1;
Q.push(x);
while (Q.size())
{
int u = Q.front(); Q.pop();
int Siz = cdp[u].size();
for (int i = 0; i < Siz; i++)
{
int v = cdp[u][i];
if (dis[x][v] == -1)
{
dis[x][v] = dis[x][u] + 1;
dp[x][dis[x][v]][v] = 1;
Q.push(v);
}
}
}
}
int main()
{
scanf("%d %d %d", &n, &m, &q);
for (int i = 1; i <= m; i++)
{
int x, y; scanf("%d %d", &x, &y);
cdp[x].push_back(y);
cdp[y].push_back(x);
}
memset(dis, 255, sizeof(dis));
for (int k = 1; k <= n; k++)
{
bfs(k);
for (int i = 1; i <= n; i++) dp[k][i] |= dp[k][i - 1];
}
while (q--)
{
int num; scanf("%d", &num);
bitset <M> ans;
for (int i = 1; i <= num; i++)
{
int x, y; scanf("%d %d", &x, &y); ans |= dp[x][y];
}
printf("%d\n", ans.count());
}
return 0;
}