【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
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
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 "); else printf("NIE "); } return 0; }