【BZOJ3417】Poi2013 Tales of seafaring

Description

一个n点m边无向图,边权均为1,有k个询问

每次询问给出(s,t,d),要求回答是否存在一条从s到t的路径,长度为d

路径不必是简单路(可以自交)

2<=N<=5000,1<=M<=5000,1<=K<=1000000,1<=d<=1000000000

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

题解:由于可以走重复的边,所以我们可以先走最短路过去,然后不断重复走同一条边。然而这样就对最短路长度的奇偶性有要求。所以我们将图分层,维护每个点到其他点的长度为奇数和偶数的最短路,用BFS即可。

然而本题卡空间所以要将询问离线。

还要特判从一个点走到自身,且这个点没有出边的情况。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn=5010;
int n,m,k,cnt;
int to[maxn<<1],next[maxn<<1],head[maxn],dis[maxn][2],ans[1000010];
queue<int> qx,qy;
struct node
{
int x,v,org;
node() {}
node(int a,int b,int c) {x=a,v=b,org=c;}
};
vector<node> p[maxn];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
int main()
{
memset(head,-1,sizeof(head));
register int i,j,a,b,c;
n=rd(),m=rd(),k=rd();
for(i=1;i<=m;i++) a=rd(),b=rd(),add(a,b),add(b,a);
for(i=1;i<=k;i++) a=rd(),b=rd(),c=rd(),p[a].push_back(node(b,c,i));
for(i=1;i<=n;i++) if(p[i].size())
{
memset(dis,-1,sizeof(dis));
dis[i][0]=0,qx.push(i),qy.push(0);
while(!qx.empty())
{
a=qx.front(),b=qy.front(),qx.pop(),qy.pop();
for(j=head[a];j!=-1;j=next[j]) if(dis[to[j]][b^1]==-1)
dis[to[j]][b^1]=dis[a][b]+1,qx.push(to[j]),qy.push(b^1);
}
for(j=0;j<(int)p[i].size();j++) if(dis[p[i][j].x][p[i][j].v&1]!=-1&&dis[p[i][j].x][p[i][j].v&1]<=p[i][j].v)
{
if(head[i]!=-1) ans[p[i][j].org]=1;
}
}
for(i=1;i<=k;i++)
{
if(ans[i]) printf("TAK\n");
else printf("NIE\n");
}
return 0;
}
05-07 11:03