题目链接:
首先这题并不难,只是duliu卡常数罢了,是Ynoi里面比较友好的一道题。
先预处理\(f[i][j]\)表示\(Dist(i,k)\le j\)的点\(k\)集合,那么对每一个点BFS一边
然后求答案的话取个并集就好了。
以上步骤都可以用bitset加速
时间复杂度 \(O(nm+\frac{n^3}{32}+\frac{n\sum a}{32})\)
还有一点,分析复杂度你会发现BFS竟然是这个题复杂度的瓶颈。。
如果你使用前向星存图就会全部TLE,可以用std::vector
或者开\(n\)个栈来存图(这题要判重边),这样由于内存连续就可以卡Cache从而AC
全手写了一边,卡了Luogu Rank2,卡常真好玩
代码:
//Absoulute LanrTabe#include#include #include #define rint register inttypedef unsigned int ui;#define Getchar (p1==p2&&(p2=(p1=In)+fread(In,1,1<<21,stdin),p1==p2)?EOF:*p1++)char In[1<<21],*p1=In,*p2=In,Ch;inline int Getint(rint x=0){ while(!isdigit(Ch=Getchar)); for(;isdigit(Ch);Ch=Getchar)x=x*10+(Ch^48); return x;}inline int Min(const int a,const int b){return a >5]|=1u<<(p&0x1f);} int Count(rint s=0){for(rint i=0;i<33;++i)s+=Cnt[a[i]&0xffff]+Cnt[a[i]>>16&0xffff];return s;} inline void operator|=(const Bitset &o){for(rint i=0;i<33;++i)a[i]|=o.a[i];}}f[1005][1005],S;int n,m,q,G[1005][1005],Gs[1005];int Dis[1005],Q[1005],Qh,Qt,Md[1005];bool Gv[1005][1005];int main(){ //freopen("in.txt","r",stdin); for(rint i=1;i<=0xffff;++i)Cnt[i]=Cnt[i>>1]+(i&1); n=Getint(),m=Getint(),q=Getint(); for(rint x,y;m--;) { x=Getint(),y=Getint(); if(!Gv[x][y]&&!Gv[y][x])G[x][++Gs[x]]=y,G[y][++Gs[y]]=x,Gv[x][y]=Gv[y][x]=true; } for(rint s=1;s<=n;++s) { memset(Dis,-1,sizeof Dis),Dis[Q[Qh=Qt=1]=s]=0; for(rint x,d;Qh<=Qt;) { d=Dis[x=Q[Qh++]],Md[s]=d,f[s][d].Set(x); for(rint i=Gs[x],y;i>=1;--i)if(Dis[y=G[x][i]]==-1)Dis[Q[++Qt]=y]=d+1; } for(rint i=1;i<=Md[s];++i)f[s][i]|=f[s][i-1]; } for(rint a,x,y;q--;printf("%d\n",S.Count())) for(S.Reset(),a=Getint();a--;S|=f[x][Min(y,Md[x])]) x=Getint(),y=Getint(); return 0;}