zoukankan      html  css  js  c++  java
  • NOIP2019普及组T4——加工零件

    一道挺好的思维题。

    题意简述

    题目链接

      给定一张边权均为1无向图,共Q次询问,每次给出两个参数a,L,询问1号点到a号点之间是否存在长度为L的路径,其中边和点可以经过多次。

    算法概述

      将1号点到每个点之间的路径长度设为dis,则对于每个询问,若L<min(dis[a]),显然无解。

      当L>=min(dis[a])时,若存在dis[a]与L奇偶性相同,则必然有解,否则无解。

      故,我们可先预处理出1号点到每个点的奇最短路和偶最短路,然后根据L的奇偶性,判断L是否大于与其奇偶性相同的最短路的长度即可。

      证明:

      先证充分性。

      简记dis[a]为d,由于d与L奇偶性相同,不妨设L=d+2*k(k∈N),那么对于1号点和a号点,必然可以找到与这两点中某一点u有直接边相连的一个点x,则可从u到x进行来回跑动,每次总距离会增加2,共跑k次,然后加上d,即可得到L的长度。充分性成立。

      必要性可用反证法同理得证。

      时间复杂度O(mlogn)

    参考代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define x first
    #define y second
    using namespace std;
    typedef pair<int,int> PII;
    const int N=1e5+10;
    struct Edge{
    	int to,next,w;
    }edge[N<<1];int idx;
    int h[N];
    
    int vis[N][2],dis[N][2];
    int n,m,q;
    
    void add_edge(int u,int v,int w){edge[++idx]={v,h[u],w};h[u]=idx;}
    
    void dijkstra()
    {
    	memset(vis,0,sizeof vis);
    	memset(dis,0x3f,sizeof dis);
    	
    	priority_queue<pair<int,PII> > q;
    	dis[1][0]=0;
    	q.push(make_pair(0,make_pair(1,0)));
    	
    	while(!q.empty())
    	{
    		pair<int,int> p=q.top().y;
    		q.pop();
    		if(vis[p.x][p.y])continue;
    		vis[p.x][p.y]=1;
    		for(int i=h[p.x];~i;i=edge[i].next)
    		{
    			int to=edge[i].to;
    			if(dis[to][0]>dis[p.x][1]+1)
    			{
    				dis[to][0]=dis[p.x][1]+1;
    				q.push(make_pair(-dis[to][0],make_pair(to,0)));
    			}
    			if(dis[to][1]>dis[p.x][0]+1)
    			{
    				dis[to][1]=dis[p.x][0]+1;
    				q.push(make_pair(-dis[to][1],make_pair(to,1)));
    			}
    		}
    	}
    }
    
    int main()
    {
    	memset(h,-1,sizeof h);
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<=m;i++)
    	{
    		int u,v;scanf("%d%d",&u,&v);
    		add_edge(u,v,1);
    		add_edge(v,u,1);
    	}
    
    	dijkstra();
    	
    	while(q--)
    	{
    		int a,l;scanf("%d%d",&a,&l);
    		if(l%2)
    		{
    			if(l>=dis[a][1])printf("Yes
    ");
    			else printf("No
    ");
    		}
    		else
    		{
    			if(l>=dis[a][0])printf("Yes
    ");
    			else printf("No
    ");
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    删库了一定要跑路吗?爱情 36 技之记忆重生!
    程序员和他的朋友们!
    聊起 BigTable,让你不再胆怯
    [Ant Design] Warning: Instance created by `useForm` is not connected to any Form element. Forget to pass `form` prop?
    Git 常用命令
    Git 名词解释
    js中void 0和undefined的区别
    js运算符优先级
    搭建React项目(低配版)
    mac常用shell指令笔记
  • 原文地址:https://www.cnblogs.com/ninedream/p/13437592.html
Copyright © 2011-2022 走看看