P1613 跑路【倍增】【最短路】

题目描述

小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零。可是小A偏偏又有赖床的坏毛病。于是为了保住自己的工资,小A买了一个十分牛B的空间跑路器,每秒钟可以跑2^k千米(k是任意自然数)。当然,这个机器是用longint存的,所以总跑路长度不能超过maxlongint千米。小A的家到公司的路可以看做一个有向图,小A家为点1,公司为点n,每条边长度均为一千米。小A想每天能醒地尽量晚,所以让你帮他算算,他最少需要几秒才能到公司。数据保证1到n至少有一条路径。

输入格式

第一行两个整数n,m,表示点的个数和边的个数。

接下来m行每行两个数字u,v,表示一条u到v的边。

输出格式

一行一个数字,表示到公司的最少秒数。

输入输出样例

输入 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
4 4
1 1
1 2
2 3
3 4
输出 #1<button class="copy&#45;btn lfe&#45;form&#45;sz&#45;middle" data&#45;v&#45;370e72e2="" data&#45;v&#45;52f2d52f="" type="button">复制</button>
1

说明/提示

【样例解释】

1->1->2->3->4,总路径长度为4千米,直接使用一次跑路器即可。

【数据范围】

50%的数据满足最优解路径长度<=1000;

100%的数据满足n<=50,m<=10000,最优解路径长度<=maxlongint。

 

思路

  由于数据量很小,可以考虑Floyd,而由于空间跳跃的缘故,直接跑Floyd出来的最短路不一定是真正的最短路。

  于是用倍增的思想来维护一下两点间的最短路。

  可以建立一个bool倍增数组 f[i][j][k] 来表示点对 i,j 间可以由空间跳跃一次跳达。

  如何处理出所有的这样的点对。

  可以枚举 K 跑 Floyd。因为是边权小于Maxlongint的,所以在 1 ~ 64 的范围内枚举k就可以了。

  令中转点为 t , 显然如果 i 到 t 是 2^(k-1) 的距离, 且 t 到 k 是 2^(k-1) 的距离,就知道一定有 i -> j 是 2 ^ k 的距离,此时更新 f[i][j][k] 和 dis[i][j] 即可。

CODE

 

 1 #include <bits/stdc++.h>
 2 #define dbg(x) cout << #x << "=" << x << endl
 3 #define eps 1e-8
 4 #define pi acos(-1.0)
 5 
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 template<class T>inline void read(T &res)
10 {
11     char c;T flag=1;
12     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
13     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
14 }
15 
16 namespace _buff {
17     const size_t BUFF = 1 << 19;
18     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
19     char getc() {
20         if (ib == ie) {
21             ib = ibuf;
22             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
23         }
24         return ib == ie ? -1 : *ib++;
25     }
26 }
27 
28 int qread() {
29     using namespace _buff;
30     int ret = 0;
31     bool pos = true;
32     char c = getc();
33     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
34         assert(~c);
35     }
36     if (c == '-') {
37         pos = false;
38         c = getc();
39     }
40     for (; c >= '0' && c <= '9'; c = getc()) {
41         ret = (ret << 3) + (ret << 1) + (c ^ 48);
42     }
43     return pos ? ret : -ret;
44 }
45 
46 const int maxn = 1e4 + 7;
47 
48 int n,m;
49 
50 bool f[100][100][100];
51 int dis[100][100];
52 
53 void init() {
54     for ( int i = 1; i <= n; ++i ) {
55         for ( int j = 1; j <= n; ++j ) {
56             if(i == j) {
57                 dis[i][j] = 0;
58             }
59             else {
60                 dis[i][j] = 0x3f3f3f3f;
61             }
62         }
63     }
64 }
65 
66 int main()
67 {
68     scanf("%d %d",&n, &m);
69     init();
70     int u, v;
71     for ( int i = 1; i <= m; ++i ) {
72         scanf("%d %d",&u, &v);
73         dis[u][v] = 1;
74         f[u][v][0] = 1;
75     }
76     for (int t = 1; t <= 64; ++t) {
77         for (int k = 1; k <= n; ++k) {
78             for (int i = 1; i <= n; ++i) {
79                 for (int j = 1; j <= n; ++j) {
80                     if(f[i][k][t-1] && f[k][j][t-1]) {
81                         f[i][j][t] = 1;
82                         if(i != j) dis[i][j] = 1;
83                         else
84                             dis[i][j] = 0;
85                     }
86                 }
87             }
88         }
89     }
90     for (int k = 1; k <= n; ++k) {
91         for (int i = 1; i <= n; ++i) {
92            for (int j = 1; j <= n; ++j) {
93                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
94             }
95         }
96     }
97     printf("%d\n",dis[1][n]);
98     return 0;
99 }
View Code

 

 

 

全部评论

相关推荐

作为带过好几个实习生的老mentor,我见过有同学带着一腔热血来实习,最后却只带走一份单薄的履历。实习,是你从学校到职场最关键的过渡期,它的价值远不止一份实习证明。今天,我不讲大道理,就从我作为Mentor的视角,给你们几条能立刻用上的建议。记住,你的目标不是当个好学生,而是成为一个值得信赖的职场新人。一、&nbsp;心态转变:从被动答题到主动解题这是我最想强调的一点。学生思维是:等待老师布置明确的作业,然后完成它。职场思维是:主动发现模糊的问题,然后解决它。反面事例:接到任务后,埋头就做,遇到困难不吭声,直到截止日期才说“这个我不会”。Mentor期待的是啥呢?首先是确认目标:接到任务后,先用自己的话复述一遍:“我理解这个任务是要达成XX效果,对吗?”&nbsp;确保方向没错。然后是主动思考:不要只带问题来,要带“选择题”。问“这个数据我不会查,我尝试了A和B方法都失败了,您看是方法C更合适,还是我有其他没考虑到的渠道?”&nbsp;这证明了你的思考和努力。最后是闭环思维:任务完成后,主动告知结果:“XX任务已完成,数据/文件已发您邮箱,并同步在团队网盘了。其中有个小发现是……,供您参考。”&nbsp;让一切有始有终。二、&nbsp;沟通方式:实习生的很多错误,都源于“想当然”和“不敢问”。反面教材:在做一个PPT时,因为不确定公司模板,就套用了自己觉得好看的模板,结果不能用。那么怎么确认,怎么提问呢?第一个,不懂就问,但别重复问:第一次问,是学习;同样的问题问第三次,就是不用心。准备一个笔记本,把关键信息、操作流程、注意事项都记下来。第二个,及时汇报,别等追问:特别是遇到卡壳或可能延期时,一定要提前说。Mentor不怕你慢,就怕你失联。没事儿更新一下进度:目前已完成80%,但在XX环节遇到点阻力,正在想办法沟通等回复,预计今天下班前确定结果,到时候给您,这样说能让人极度安心。第三个,珍惜1on1机会:和Mentor的定期沟通,不是你被动接受批评,而是你主动获取信息和反馈的黄金时间。提前准备好:a)&nbsp;本周工作进展;b)&nbsp;遇到的困惑/挑战;c)&nbsp;希望学习的新技能;d)&nbsp;对团队业务的任何好奇。三、&nbsp;工作习惯:&nbsp;专业性体现在细节里职业素养不是空话,它藏在每一个你容易忽略的细节中。1.&nbsp;邮件/沟通软件礼仪:邮件:标题清晰(如【实习生XX-XX项目周报】),正文称呼得体,结尾有落款。别用“在吗?”开头。工作群:别发表情包刷屏,沟通事情简明扼要。收到任务或通知,回复“收到,谢谢”,这是基本的确认和尊重。2.&nbsp;文件管理与命名:我会观察实习生的桌面,看他们的使用习惯,乱糟糟的桌面说明他没条理。文件命名要使用统一的命名规则:日期_项目名_内容_版本_姓名。例如:20231027_秋招海报_初版_张三。这能为整个团队节省大量沟通成本。3.&nbsp;对待杂活的态度:复印、整理数据、会议纪要……这些dirty&nbsp;work是不可避免的。但优秀的人是能从中找到价值的:整理数据时,可以留意数据之间的关联或异常,做会议纪要时,可以梳理出会议的决策和待办事项。四、&nbsp;终极目标:带走三样东西1.&nbsp;一段能讲出STAR法则的实战经历:这直接决定了你未来求职简历的厚度。2.&nbsp;一位可以为你未来背书的Mentor/同事:好好表现,离职时保持联系,他们可能成为你未来求职的推荐人和内推渠道。3.&nbsp;对行业和岗位的真实认知:通过这次实习,你想清楚自己是更热爱这个行业,还是想赶紧跑路?这个答案,价值千金。最后,作为你们的Mentor,我想说:大胆去试,勇敢去问,别怕犯错。实习期是你犯错成本最低的时候。展现出你的靠谱、主动和思考,我们做Mentor的,会非常乐意把更核心的任务交给你,因为带你,也是在为团队培养未来的战友。希望这些建议能帮你少走弯路,打一场漂亮的实习战!
家族企业:实习一年比在大学多年都有用
第一次找实习,我建议__
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务