传送门
预处理 d i s [ i ] [ j ] dis[i][j] dis[i][j]表示 i − > j i->j i−>j的最短路
这步是 O ( n m ) O(nm) O(nm)的复杂度
然后对于所有的 q q q次询问
每一对二元组 ( x , y ) (x,y) (x,y)都对每个点扫一遍
这样复杂度是 O ( 2100000 n ) O(2100000n) O(2100000n),时间复杂度上天
考虑用 b i t s e t bitset bitset优化
由于二元组 ( x , y ) (x,y) (x,y)只有 1000 ∗ 1000 1000*1000 1000∗1000种取值
直接预处理在 b i t [ i ] [ j ] bit[i][j] bit[i][j]压缩每个点是否能够通过
然后直接输出就行了
存图用链式前向星会被卡
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
//struct edge{
// int to,nxt;
//}d[maxn]; int head[maxn],cnt=1;
//void add(int u,int v)
//{
// d[++cnt] = (edge){v,head[u]},head[u] = cnt;
//}
vector<int>vec[1001];
int dis[1001][1001],n,m,q;
bool vis[1001];
bitset<1001>bit[1001][1001];
void bfs(int s)
{
queue<int>q;
q.push(s); dis[s][s] = 0;
for(int i=0;i<=n;i++) vis[i] = 0;
vis[s] = 1;
while( !q.empty() )
{
int u = q.front(); q.pop();
// for(int i=head[u];i;i=d[i].nxt )
int sd = vec[u].size();
for(int i=0;i<sd;i++)
{
int v = vec[u][i];
if( vis[v] ) continue;
vis[v] = 1;
dis[s][v] = dis[s][u]+1;
q.push( v );
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++)
{
int l,r; scanf("%d%d",&l,&r);
vec[l].push_back(r);
vec[r].push_back(l);
}
memset( dis,-1,sizeof dis);
for(int i=1;i<=n;i++)
{
bfs(i);
for(int j=0;j<=n;j++)
if( dis[i][j]!=-1 ) bit[i][dis[i][j]][j] = 1;
for(int j=1;j<=n;j++) bit[i][j] |= bit[i][j-1];
}
for(int i=1;i<=q;i++)
{
int now; scanf("%d",&now);
bitset<1001>ans;
for(int j=1;j<=now;j++)
{
int x,y; scanf("%d%d",&x,&y);
ans |= bit[x][y];
}
printf("%d\n",ans.count() );
}
}