CSDN同步

原题链接

简要题意:

给定一个图,每次询问从 \(x\) 节点开始,\(y\) 步能不能达到 \(1\) 号节点。

算法一

这也是我本人考场算法。就是 深搜

因为你会发现,如果 \(x\) 用 \(y \% 2\) 步能到 \(1\) 节点,那肯定 \(y\) 步能到。

原因是:剩下的 \(y - y \% 2\) 是偶数,只要重复走一条边多次即可。

我们用 \(f_{i,0/1}\) 表示,从 \(i\) 号节点经过 偶数步(0) 奇数步(1) 能到 \(1\) 号节点的最短步数。

从 \(1\) 开始深搜即可。如果已有答案当前答案更优,则结束。

时间复杂度:\(O(n^2)\).(代码后会解释)

实际得分:\(80pts\).(考场上也就这么多)

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std; const int N=1e5+1; inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;} int f[N][2];
int n,m,q;
vector<int>G[N]; inline void dfs(int dep,int bs) {
if(f[dep][bs%2]!=-1 && f[dep][bs%2]<=bs) return; //无需更新答案
f[dep][bs%2]=bs; //记录答案
for(int i=0;i<G[dep].size();i++) {
int x=G[dep][i];
dfs(G[dep][i],bs+1);
}
} int main(){
n=read(),m=read(),q=read();
memset(f,-1,sizeof(f));
while(m--) {
int x=read(),y=read();
G[x].push_back(y);
G[y].push_back(x);
} f[1][0]=2; dfs(1,0);
while(q--) {
int x=read(),y=read();
if(f[x][y%2]!=-1 && f[x][y%2]<=y) puts("Yes");
else puts("No");
} //判断
return 0;
}

你会说,这个程序的时间复杂度是 \(O(n)\) 吧?怎么是 \(O(n^2)\)?

这个问题也困扰了我很久,以至于很难想清楚,怎样的一种情况可以卡掉它。

重写了代码之后就发现了。

因为,如果是个完全图的话,每个点都会被其它点到达(尽管被 \(\texttt{return}\) 但还是做了),所以是 \(O(n^2)\).

你会说,那也不会是完全图啊?\(n\) 和 \(m\) 是同阶啊?

也对。所以完全图不用考虑,给定图肯定是稀疏图。

那么,问题在哪儿?

你想,如果原图是一个长 \(10^5\) 的一个环。

此时,这个程序极有可能炸掉。

因为,如果你的遍历顺序一路走完了这个环,然后又走一遍(因为奇偶性不同,导致走 \(2\) 次)。

接着,里面的每个点的探索次数为 \(2\),也就是说每个点又开始向其它点探索。

但是,假设你在第三次走环的时候 \(1\) 结束掉,此时 \(n\) 号节点就返到 \(n-1\) 号节点。

然后 \(n-1\) 号节点的递归次数就变成 \(2\),它把锅都甩给了两边,又到了 \(n\),然后才结束。

每个点都把自己身上的锅(就是递归次数)扔给相邻的,但是,你必须要走 \(n\) 次(就到头) 才可以确定一个节点的答案。

此时 \(O(n^2)\).

那么,如何优化这个程序呢?

算法二

深搜不行,用宽搜。

用了宽搜就不存在 “互相甩锅” 这个问题。每个人只会甩常数次锅。

时间复杂度:\(O(n+m)\).(\(n\) 有系数,但被忽略)

实际得分:\(100pts\).

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std; const int N=1e5+1; inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;} int f[N][2];
int n,m,q;
vector<int>G[N]; inline void bfs() {
queue<pair<int,int> >q;
memset(f,0x3f,sizeof(f));
for(int i=0;i<G[1].size();i++) {
f[G[1][i]][1]=1; //与1相邻的点,奇数步能到达1
q.push(make_pair(G[1][i],1)); //入队
} while(!q.empty()) {
int x=q.front().first,y=q.front().second;
q.pop();
for(int i=0;i<G[x].size();i++) {
int k=G[x][i];
if(y+1<f[k][1-y%2]) {
f[k][1-y%2]=y+1;
q.push(make_pair(k,y+1)); //入队
} //1-y%2,就是 (y+1)%2,改变奇偶性后 0->1,1->0,正好用 1 减掉。
}
}
} int main(){
n=read(),m=read(),q=read();
while(m--) {
int x=read(),y=read();
G[x].push_back(y);
G[y].push_back(x);
} bfs();
while(q--) {
int x=read(),y=read();
if(f[x][y%2]<=y) puts("Yes");
else puts("No");
}
return 0;
}

后记

这个题目说明几点:

  • 宽搜不一定旁边要开哈希。

  • 深搜有的时候难以处理极大环。

P5663 加工零件 题解的更多相关文章

  1. P5663 加工零件

    P5663 加工零件 题解 暴力搜索 搜索显然会TLE #include<iostream> #include<cstdio> #include<cstdlib> ...

  2. 洛谷 P5663 加工零件

    题目传送门 解题思路: 最暴力的做法: bfs模拟,每次将一个阶段的所有点拿出来,将其所有直连的点都放进队列,知道本阶段结束,最后看1号点会不会在最后一个阶段被放入队列.(洛谷数据40分) 优化了一下 ...

  3. 洛谷 P5663 加工零件 & [NOIP2019普及组] (奇偶最短路)

    传送门 解题思路 很容易想到用最短路来解决这一道问题(题解法),因为两个点之间可以互相无限走,所以如果到某个点的最短路是x,那么x+2,x+4也一定能够达到. 但是如何保证这是正确的呢?比如说到某个点 ...

  4. 题解 P5663 【加工零件【民间数据】】

    博客园体验更佳 讲讲我的做法 确定做法 首先,看到这道题,我直接想到的是递归,于是复杂度就上天了,考虑最短路. 如何用最短路 首先,看一张图 我们该如何解决问题? 问题:\(3\)做\(5\)阶段的零 ...

  5. 题解 CSP2019-J2T4【加工零件】

    这题我们要求的是啥呢?仔细读题可以发现,工人传送带的关系可以看成一个 \(n\) 个点和 \(m\) 条边的无向图,然后对于每组询问 \((a,L)\),其实就是问: \(1\) 到 \(a\) 有没 ...

  6. 2019CSP-J T4 加工零件

    题目描述 凯凯的工厂正在有条不紊地生产一种神奇的零件,神奇的零件的生产过程自然也很神奇.工厂里有 n 位工人,工人们从 1 ∼n 编号.某些工人之间存在双向的零件传送带.保证每两名工人之间最多只存在一 ...

  7. CSP-J2019 加工零件

    Background: 之前 $noip $死了,泥萌都说 \(noip SPFA\) 了,现在 \(noip\) 复活了,所以 \(SPFA\) 也复活了. (注:这里的 \(noip\) 跟 \( ...

  8. 2019年CPS-J复赛题解

    题目涉及算法: 数字游戏:字符串入门题: 公交换乘:模拟: 纪念品:完全背包: 数字游戏:广搜/最短路. 数字游戏 题目链接:https://www.luogu.com.cn/problem/P566 ...

  9. 题解 CF1304E 【1-Trees and Queries】

    前言 这场比赛,在最后 \(5\) 分钟,我想到了这道题的 \(Idea\),但是,没有打完,比赛就结束了. 正文 题目意思 这道题目的意思就是说,一棵树上每次给 \(x\) 和 \(y\) 节点连 ...

随机推荐

  1. Google在百慕大避税几十亿美金,为什么巨头和富豪都会选百慕大避税?

    为什么"越有钱越有钱"?为什么富豪只要不自己"作",就能让自己的财富疯狂增加?除了经营意识之外,关键他们还可以利用自己的资源.实力等去做很多看似让人不齿,但其实 ...

  2. 【转载】ArcGIS中的WKID

    原出处:http://www.cnblogs.com/liweis/p/5951032.html 提到坐标系统,大家多少能明白一些,但在运用时,有些朋友搞得不是非常清楚,以后专门来总结.在实地生产项目 ...

  3. python类变量与构造函数的使用

    类变量:可在类的所有实例之间共享的变量 实例类对象:类的实例是调用类对象来创建的.如:par = Parent(),par就是类Parent的一个实例类对象. 实例变量(成员变量):同一个类对象可以创 ...

  4. go语言指南之映射练习

    练习:映射 实现 WordCount.它应当返回一个映射,其中包含字符串 s 中每个“单词”的个数.函数 wc.Test 会对此函数执行一系列测试用例,并输出成功还是失败. 你会发现 strings. ...

  5. svg和css3创建环形渐变进度条

    在负责的项目中,有一个环形渐变读取进度的效果的需求,于是在网上查阅相关资料整理一下.代码如下: <!DOCTYPE html> <html lang="en"&g ...

  6. 「前端」rem 缩放方案 flexible-js 兼容 375px 方案的思路

    本文来自尚妆前端团队南洋 发表于尚妆github博客,欢迎订阅. 移动端H5页面rem缩放方案flexible.js兼容375px方案的思路 参考: 移动端高清.多屏适配方案 viewport-and ...

  7. 必备技能六、Vue框架引入JS库的正确姿势

    在Vue.js应用中,可能需要引入Lodash,Moment,Axios,Async等非常好用的JavaScript库.当项目变得复杂庞大,通常会将代码进行模块化拆分.可能还需要跑在不同的环境下,比如 ...

  8. 盘点Linux运维常用工具(二)-web篇之nginx

    1.nginx的概述 .nginx是一个开源的.支持高性能.高并发的WWW服务和代理服务软件 .是由俄罗斯人Igor Sysoev开发的,具有高并发.占用系统资源少等特性 .官网:http://ngi ...

  9. String常见的方法有哪些?

    length();//计算字符串的长度 charAt();//截取一个字符 getChars();//截取多个字符 equals();//比较两个字符串 equalsIgnoreCase();//比较 ...

  10. 微信SEO怎么做-最新微信SEO干货

    星辉信息科技进行微信SEO已经很多年了,结合多年的微信SEO经验通过浅谈微信SEO.微信SEO的3大优势.微信SEO的6个排名技巧.企业和个人微信SEO的4大优化战略来讲,可以完美解决B端C端微信获客 ...