[洛谷P5068][Ynoi2015]我回来了

题目大意:给你一张$n(nleqslant10^3)$个点$m(mleqslant10^5)$个点的无向无权图,多组询问,每次询问给你一些二元组$(x_i,y_i)$,求有多少个$u$于至少一个二元组满足:$dis(u,x_i)leqslant y_i$

题解:对每个点跑一遍$bfs$,求出每个点到达其他点的距离,按距离前缀和一下(就是说变成小于等于这个距离是哪几个点),$f_{i,j}$表示到第$i$个点距离小于等于$j$的点有哪些,查询时把答案与$f_{x,y}$求个并集就行了,可以用$bitset$优化

复杂度:$O(dfrac{n^3}{omega})$,可以通过

卡点:用前向星存边被卡常,需要用$vector$(可能是因为边数较大,$vector$内存访问连续)

C++ Code:

#include <iostream>
#include <cstring>
#include <bitset>
#include <vector>
#define maxn 1024
#define maxm 100010
const int inf = 0x3f3f3f3f;

std::vector<int> e[maxn];

int n, m, Q;
std::bitset<maxn> v[maxn][maxn];
int d[maxn], q[maxn], h, t;
int MAXL[maxn];
void bfs(int S, std::bitset<maxn> *v) {
	memset(d, 0, sizeof d);
	q[h = t = 0] = S;
	while (h <= t) {
		int u = q[h++];
		v[d[u]].set(u);
		const std::vector<int>::iterator End = e[u].end();
		for (std::vector<int>::iterator it = e[u].begin(); it != End; ++it) {
			int v = *it;
			if (v != S && !d[v]) {
				d[v] = d[u] + 1;
				q[++t] = v;
			}
		}
	}
	const int M = d[q[t]];
	for (int i = 1; i <= M; i++) v[i] |= v[i - 1];
	MAXL[S] = M;
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	std::cin >> n >> m >> Q;
	for (int i = 0, a, b; i < m; i++) {
		std::cin >> a >> b;
		e[a].push_back(b);
		e[b].push_back(a);
	}
	for (int i = 1; i <= n; i++) bfs(i, v[i]);
	while (Q --> 0) {
		std::bitset<maxn> ans;
		int T;
		std::cin >> T;
		while (T --> 0) {
			int x, y;
			std::cin >> x >> y; if (y > MAXL[x]) y = MAXL[x];
			ans |= v[x][y];
		}
		std::cout << ans.count() << '
';
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/10107555.html