链接:
https://www.nowcoder.com/acm/contest/82/E
来源:牛客网
来源:牛客网
题目描述
有一个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,m,q
之后m行每行两个数x,y表示有一条x与y之间的边,边权为1
之后q次询问,每个询问先给你一个数a
之后一行2a个数,第2i-1个数x
i和第2i个数y
i表示一个二元组(x
i,y
i)
输出描述:
输出q行,每行一个数表示这次询问的答案
题解:
开始在想为什么边的长度都为1,如边的长度随意的话只是求个多源最短路时间就超了,
但是由于边长都为1,可以直接bfs求出最短路。
枚举每一个出发到所有点的最短路,可以在1000*100000的时间内求得。
0<=x,y<=1000,一共有1000000种组合,可以先打个表,用bitset存储
然后2100000*1000/64的时间内求出答案。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1002;
bitset<maxn>bit[maxn][maxn];
int d[maxn][maxn], n;
bool is[maxn];
vector<int>p[maxn];
queue<int>P;
void bfs(int id)
{
memset(is, 0, sizeof(is));
is[id] = 1;
d[id][id] = 0;
P.push(id);
while (!P.empty())
{
int v = P.front(); P.pop();
int L = p[v].size();
for (int i = 0; i<L; i++)
{
int to = p[v][i];
if (!is[to])
{
is[to] = 1;
P.push(to);
d[id][to] = d[id][v] + 1;
}
}
}
}
int main()
{
int m, Q; scanf("%d%d%d", &n, &m, &Q);
for (int i = 0; i<m; i++)
{
int x, y; scanf("%d%d", &x, &y);
p[x].push_back(y);
p[y].push_back(x);
}
memset(d, -1, sizeof(d));
for (int i = 1; i <= n; i++)
{
bfs(i);
for (int j = 0; j <= n; j++)
if(d[i][j]!=-1)bit[i][d[i][j]][j] = 1;
for (int j = 1; j <= n; j++)bit[i][j] |= bit[i][j - 1];
}
while (Q--)
{
int T; scanf("%d", &T);
bitset<maxn>ans;
while (T--)
{
int x, y; scanf("%d%d", &x, &y);
ans |= bit[x][y];
}
printf("%d\n", ans.count());
}
return 0;
}