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

     

  • 相关阅读:
    C# 获取命名空间对应的程序集位置
    启用/禁用以太网的批处理,用于一个网卡切换本地网络和wifi使用(Win10)
    Gogs/Gitea 在 docker 中部署
    bash echo color
    python运行httpserver
    更改当前启动项,开关Hyper-V
    Win10更改CMD控制台的代码页和字体和字号
    ubuntu 编译 vim+lua
    CPU Usage (C#) 测试
    单击改变input的边框颜色
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7787796.html
Copyright © 2020-2023  润新知