题目大意:给n个点m条边无向图,每次询问两个点之间是否有长度为d的路径(不一定是简单路径)
从a到b假如有长度为x的路径,那就可以往回走一步再往前走一步得到长度为x+2的路径
所以可以求出每对点之间的奇数长度最短路和偶数长度最短路,然后判断是否小于d即可
PS:
1.这题卡内存,所以必须离线之后一个点一个点的枚举起点算完之后重新利用内存
2.会有单点不与外界联通并查询这个单点自己之间是否有长度为d的情况,需要特判!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10010
#define M 1000010
using namespace std;
int to[N<<1],nxt[N<<1],pre[N],cnt;
void ae(int ff,int tt)
{
cnt++;
to[cnt]=tt;
nxt[cnt]=pre[ff];
pre[ff]=cnt;
}
struct ppp{int a,b,k,num;}a[M];
bool cmp(ppp x,ppp y){return x.a<y.a;}
int d[N],q[N*10];
void spfa(int S)
{
int h=1,t=1;
memset(d,0x3f,sizeof(d));
q[1]=S;d[S]=0;
int i,j,x;
while(h<=t)
{
x=q[h];h++;
for(i=pre[x];i;i=nxt[i])
{
j=to[i];
if(d[j]!=0x3f3f3f3f) continue;
d[j]=d[x]+1;
t++;q[t]=j;
}
}
}
bool ans[M];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
int i,j,x,y;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
ae(x,y+n);ae(x+n,y);
ae(y,x+n);ae(y+n,x);
}
for(i=1;i<=k;i++)
scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].k),a[i].num=i;
sort(a+1,a+k+1,cmp);
j=1;
for(i=1;i<=n;i++)
{
spfa(i);
while(a[j].a==i)
{
if(a[j].a==a[j].b&&!pre[a[j].a])
{
if(a[j].k==0) ans[a[j].num]=true;
else ans[a[j].num]=false;
}
else
{
if(a[j].k&1)
{
if(d[a[j].b+n]<=a[j].k)
ans[a[j].num]=true;
}
else
{
if(d[a[j].b]<=a[j].k)
ans[a[j].num]=true;
}
}
j++;
}
}
for(i=1;i<=k;i++)
if(ans[i]) puts("TAK");
else puts("NIE");
}