我是仙人掌 社论

闲话被虎哥扬了,哼哼啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!

遂水篇博客 .


我是仙人掌

珂朵莉给你一个无向图,每次查询的时候给一堆二元组 \((x_i,y_i)\) .

求图中有多少个点 \(u\) 与至少一个这次询问给出的二元组 \((x_i,y_i)\) 满足 \(\operatorname{dist}(u,x_i)\leq y_i\)\(\operatorname{dist}\) 表示这两个点在图中的距离 .

如果不连通 \(\mathrm{dist} = +\infty\) .

\(1\leq n\leq 1000\)\(1\leq m,q \leq 10^5\)\(\sum a\leq2.1\times 10^6\) .

首先 \(n\) 遍 BFS 求出全源最短路 .

然后我们就可以算出从每个点 \(i\) 出发,最短路恰好为 \(j\) 的点的集合,前缀或一遍就可以得到不大于 \(j\) 的集合(用 std :: bitset 存一下).

询问的时候直接 bitset 暴力并一下即可,时间复杂度 \(\displaystyle O\left(n^2+nm+\left(n^3+n\sum a\right)/w\right)\)


代码(2021/7/13):

using namespace std;
const int N=1234;
vector<int> g[N];
bitset<N> F[N][N];
int n,m,q,dis[N];
void addedge(int u,int v){g[u].push_back(v);}
void bfs(int x)
{
	for (int i=1;i<=n;i++) dis[i]=2222;
	queue<int> q; q.push(x); dis[x]=0;
	while (!q.empty())
	{
		int u=q.front(),s=g[u].size(); q.pop();
		for (int i=0;i<s;i++)
		{
			int v=g[u][i];
			if (dis[v]==2222){dis[v]=dis[u]+1; q.push(v);}
		}
	}
	for (int i=1;i<=n;i++) F[x][dis[i]].set(i);
	for (int i=1;i<=n;i++) F[x][i]|=F[x][i-1];
}
int main()
{
	scanf("%d%d%d",&n,&m,&q);
	for (int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
	for (int i=1;i<=n;i++) bfs(i);
	int a;
	while (q--)
	{
		scanf("%d",&a);
		bitset<N> ans;
		for (int i=1,u,v;i<=a;i++){scanf("%d%d",&u,&v); ans|=F[u][v];}
		printf("%d\n",int(ans.count()));
	} return 0;
}
posted @ 2022-08-17 16:28  Jijidawang  阅读(90)  评论(0编辑  收藏  举报
😅​