- 题面·一本通
- 两种实现方式,广搜和SPFA
其实还想写dijkstra,但是只有80分,剩下的都超时或者WA了- 主要注意可以两个人互相给,所以要分奇偶存储
- 还有10^5邻接表存不下,要用链式前向星(主要是我就会这个)
广搜
解释
完整代码
#include<bits/stdc++.h>
using namespace std;
struct cyy{
int to,next;
}a[300010];
int h[300010],d[300010][2];
long long n,m,q,cnt=0;
void add(int x,int y){
a[++cnt].to=y;
a[cnt].next=h[x];
h[x]=cnt;
}
queue<long long> f;
void bfs()
{
d[1][0]=0;
f.push(1);
while(!f.empty()){
int x=f.front();f.pop();
for(int j=h[x];j;j=a[j].next){
int i=a[j].to;
int x1=d[i][0],y1=d[i][1];
d[i][0]=min(d[i][0],d[x][1]+1);
d[i][1]=min(d[i][1],d[x][0]+1);
if(x1!=d[i][0]||y1!=d[i][1])f.push(i);
}
}
}
int main()
{
memset(d,0x7f,sizeof(d));
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
bfs();
for(long long i=1;i<=q;i++){
int u,v;
scanf("%d%d",&u,&v);
if(v%2==0&&d[u][0]<=v)printf("Yes\n");
else if(v%2==1&&d[u][1]<=v)printf("Yes\n");
else printf("No\n");
}
return 0;
}
SPFA
解释
- 其实和广搜差不多
- 那就不说了
- 剩下的和上面一模一样,不写了。
其实是懒
代码
queue<long long> f;
bool v[300010]={0},flag;
void spfa()
{
d[1][0]=0;
f.push(1);
while(!f.empty()){
flag=0;
int t=f.front();f.pop();v[t]=0;
for(int i=h[t];i;i=a[i].next){
int j=a[i].to;
if(d[j][0]>d[t][1]+1)flag=1,d[j][0]=d[t][1]+1;
if(d[j][1]>d[t][0]+1)flag=1,d[j][1]=d[t][0]+1;
if(flag==1&&!v[j]){
f.push(j);
v[j]=1;
}
}
}
}
dijkstra(80分)
bool b[300010][2]={0};
void dijkstra()
{
d[1][0]=0;
int x=(n<<1);
while(x--){
int mina=2139062143,minb=2139062143,k1=0,k2=0,k=0;
for(int j=1;j<=n;j++){
if(mina>d[j][0]&&!b[j][0]) mina=d[j][0],k1=j;
if(minb>d[j][1]&&!b[j][1]) minb=d[j][1],k2=j;
}
if(k1==k2)x--,k=k1,b[k1][0]=b[k2][1]=1;
else{
if(mina<=minb&&k1!=0){
b[k1][0]=1;
k=k1;
}
else if(mina>minb&&k2!=0){
b[k2][1]=1;
k=k2;
}
}
for(int j=h[k];j;j=a[j].next){
int t=a[j].to;
d[t][0]=min(d[k][1]+1,d[t][0]),d[t][1]=min(d[k][0]+1,d[t][1]);
}
}
}