【BZOJ3417】Poi2013 Tales of seafaring 分层图BFS

【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;
}

 

posted @ 2017-11-05 16:48  CQzhangyu  阅读(...)  评论(...编辑  收藏