题意
一个n点m边无向图,边权均为1,有k个询问,每次询问给出(s,t,d),要求回答是否存在一条从s到t的路径,长度为d,路径不必是简单路(可以自交)。
n,m<=5000,k<=1000000,d<=1000000000
分析
考虑到若从s可以走d步到达t,则s必然可以走t+2步到达t,所以只要从每个点开始看该点能否通过奇数步或偶数步到达某个点即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 5005;
const int M = 1000005;
int n, m, q, dis[N][2];
bool ans[M];
vector<int> e[N], vec[N];
struct data{int x, y, d;}a[M];
queue<pair<int, int> > que;
void bfs(int s)
{
for (int i = 1; i <= n; i++) dis[i][0] = dis[i][1] = n;
dis[s][0] = 0; que.push(make_pair(s, 0));
while (!que.empty())
{
int x = que.front().first, y = que.front().second; que.pop();
for (int to : e[x])
if (dis[to][y ^ 1] == n) dis[to][y ^ 1] = dis[x][y] + 1, que.push(make_pair(to, y ^ 1));
}
}
int main()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= m; i++)
{
int x, y; scanf("%d%d", &x, &y);
e[x].push_back(y); e[y].push_back(x);
}
for (int i = 1; i <= q; i++)
{
int x, y, d; scanf("%d%d%d", &x, &y, &d);
a[i] = (data) {x, y, d};
vec[x].push_back(i);
}
for (int x = 1; x <= n; x++)
{
bfs(x);
for (int id : vec[x])
{
int y = a[id].y, d = a[id].d;
if (dis[y][d & 1] < n && dis[y][d & 1] <= d && e[x].size() || x == y && !d) ans[id] = 1;
}
}
for (int i = 1; i <= q; i++) puts(ans[i] ? "TAK" : "NIE");
return 0;
}