Description
给定一个 n 个点 m 条边的无向图,进行多次询问,每次询问点 a 是否能经过恰好 c 条边到达点 b(当然,可以对于一条边可以来回经过多次) 。
Input
第一行三个数 n,m,q,其中 q 表示询问数。
接下来 q 行,每行三个数 a,b,c。
Output
对于每次询问,如果存在一种走法,输出 TAK,否则输出 NIE
Sample Input
8 7 4
1 2
2 3
3 4
5 6
6 7
7 8
8 5
2 3 1
1 4 1
5 5 8
1 8 10
Sample Output
TAK
NIE
TAK
NIE
Data Constraint
对于 50%的数据,n<=800。
对于 100%的数据,2<=n<=5000,1<=m<=5000,1<=q<=1000000,1<=a,
b<=n,1<=c<=10^9。
Solution
分走的步长的奇偶性以每个点为源点各做一遍SPFA(无松弛操作),只需多开一维0/1即可。
直接判断 c 是否大于等于
a 到 b 的最短路并判断奇偶性。因为可以在一条边上不断重复走(两步两步地走,奇偶性不变)。
注意特判自环且没出边的情况。
时间复杂度
O(N2+Q) 。
Code
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
const int N=5005;
int tot;
int first[N],next[N<<1],en[N<<1];
int q[N*N/3][2],dis[N][N][2],d[N];
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline void insert(int x,int y)
{
next[++tot]=first[x];
first[x]=tot;
en[tot]=y;
d[x]++;
}
inline void spfa(int s)
{
memset(dis[s],60,sizeof(dis[s]));
int l=dis[s][q[1][0]=s][0]=0,r=1;
while(l<r)
{
int x=q[++l][0],y=q[l][1];
for(int i=first[x];i;i=next[i])
if(dis[s][x][y]+1<dis[s][en[i]][y^1])
{
dis[s][en[i]][y^1]=dis[s][x][y]+1;
q[++r][0]=en[i];
q[r][1]=y^1;
}
}
}
int main()
{
int n=read(),m=read(),q=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
insert(x,y);
insert(y,x);
}
for(int i=1;i<=n;i++) spfa(i);
while(q--)
{
int x=read(),y=read(),z=read();
if(x==y && !d[x]) puts("NIE"); else
puts(z>=dis[x][y][z&1]?"TAK":"NIE");
}
return 0;
}