http://main.edu.pl/en/archive/oi/20/mor
给定一张无向图,图中每条边边权均为1,多次询问是否存在一个长度为 d ,从点 x 到点 y 的路径。
注意到虽然询问次数非常多,但是点数和边数非常少。
考虑对询问进行排序,每次统一回答一些起点相同的询问。
注意到一条长度为 d 的路径,可以通过反复走某条边,变成长度为 d+2,d+4... 的路径。
因此,以点 S 为起点BFS时,可以记录下从 S 到某个点长度为偶数和奇数的最短路长度。假如当前的询问是从 S 到 x 的长度为 d 的路径,且 d 为偶数,那么若从 S 到点 x 长度为偶数的最短路是小于等于 d 的,则表明有解,否则显然是无解的。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXE 5100
#define MAXV 5100
using namespace std;
struct edge
{
int u,v,next;
}edges[MAXE*2];
int head[MAXV],nCount=0;
void AddEdge(int U,int V)
{
edges[++nCount].u=U;
edges[nCount].v=V;
edges[nCount].next=head[U];
head[U]=nCount;
}
struct Node
{
int x,flag;
Node(){}
Node(int _x,int _f):x(_x),flag(_f){}
}q[MAXE*2];
int mindist[MAXV][2]; //mindist[i][0]=S到点i的长度为偶数的路径个数
void BFS(int S)
{
memset(mindist,-1,sizeof(mindist));
mindist[S][0]=0;
int h=0,t=1;
q[h]=Node(S,0);
while(h<t)
{
Node now=q[h++];
int u=now.x;
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(mindist[v][now.flag^1]==-1)
{
mindist[v][now.flag^1]=mindist[u][now.flag]+1;
q[t++]=Node(v,now.flag^1);
}
}
}
}
struct Query
{
int S,T,dis,id;
bool ans;
}query[1100000];
bool cmp(Query a,Query b)
{
return a.S<b.S;
}
bool cmp2(Query a,Query b)
{
return a.id<b.id;
}
int n,m,K;
bool connected[MAXV];
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
AddEdge(u,v);
AddEdge(v,u);
connected[u]=connected[v]=true;
}
for(int i=1;i<=K;i++)
{
query[i].id=i;
scanf("%d%d%d",&query[i].S,&query[i].T,&query[i].dis);
}
sort(query+1,query+K+1,cmp);
for(int i=1;i<=K;i++)
{
int tmp=i;
BFS(query[i].S);
while(i<=K&&query[i].S==query[tmp].S)
{
if(query[i].S==query[i].T&&!connected[query[i].S]) query[i].ans=false; //!!!!注意特判
else
{
if(query[i].dis&1)
{
if(query[i].dis>=mindist[query[i].T][1]&&mindist[query[i].T][1]!=-1)
query[i].ans=true;
else query[i].ans=false;
}
else
{
if(query[i].dis>=mindist[query[i].T][0]&&mindist[query[i].T][0]!=-1)
query[i].ans=true;
else query[i].ans=false;
}
}
i++;
}
i--;
}
sort(query+1,query+K+1,cmp2);
for(int i=1;i<=K;i++)
{
if(query[i].ans)
printf("TAK\n");
else
printf("NIE\n");
}
return 0;
}