JZOJ 5932. 【NOIP2018模擬10.27】情報中心

題目

給定一個點數爲n個圖,m條邊。
走一條邊算1步。
共有q個詢問
每個詢問中有k個點,求有多少個點可以走最多v步走到詢問中的任意一個點。
數據範圍 n<=1000,m<=100000n<=1000,m<=100000

題解

其他獵奇的方法

一個O(mq)的失敗方法:排個序做,每個點有一個狀態t,表示點t仍可以走t的時間。
靈感來源於剩餘相同的時間點可以一起做(序列中連續一段點的t都是相同的)。

正解

尋址優化。將前向星換成邊集數組。
bitset替換統計哪些點是否出現過的bool數組。
spfa,其中不需要鬆弛。

反思

沒拍,比賽快結束的時候發現有錯,趕緊調,結果沒有發現完所有的sb錯誤。
bitset操作:大佬的博客請點此處

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<bitset>
#include<algorithm>
#define N 1005
#define P(a) putchar(a)
using namespace std;
int i,j,k,l,n,m,q;
int cx[N],map[N][N];
int u,v,qu[N],dis[N];
bool Bz[N][N];
bitset<N>d[N][N],ans;
int read(){
	int fh=0,rs=0;char ch=0;
	while((ch<'0'||ch>'9')&&(ch^'-'))ch=getchar();
	if(ch=='-')fh=1,ch=getchar();
	while(ch>='0'&&ch<='9')rs=(rs<<3)+(rs<<1)+(ch^'0'),ch=getchar();
	return fh?-rs:rs;
}
void write(int x){
	if(x>9)write(x/10);
	P(x%10+'0');
}
int main(){
	freopen("center.in","r",stdin);
	freopen("center.out","w",stdout);
	n=read(),m=read(),q=read();
	for(i=1;i<=m;i++)u=read(),v=read(),(!Bz[u][v]?Bz[u][v]=Bz[v][u]=1,map[u][++cx[u]]=v,map[v][++cx[v]]=u:0);
	for(u=1;u<=n;u++){
		for(i=1;i<=n;i++)dis[i]=2139062143;
		dis[u]=0;
		qu[l=1]=u;
		for(i=1;i<=l;i++){
			v=qu[i];
			for(j=1;j<=cx[v];j++)(dis[map[v][j]]>dis[v]+1?dis[map[v][j]]=dis[v]+1,qu[++l]=map[v][j]:0);
		}
		for(i=1;i<=n;i++)(dis[i]<2139062143?d[u][dis[i]][i]=1:0);
		for(i=1;i<=n;i++)d[u][i]|=d[u][i-1];
	}
	while(q--){
		k=read();ans.reset();
		while(k--){
			u=read(),v=read();
			ans|=d[u][v];
		}
		write(ans.count()),P('\n');
	}
	return 0;
}
發佈了343 篇原創文章 · 獲贊 802 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章