首页 技术 正文
技术 2022年11月6日
0 收藏 885 点赞 493 浏览 1782 个字

P1613 跑路

题目描述

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

输入输出格式

输入格式:

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

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

输出格式:

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

说明

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

\(100\)%的数据满足\(n<=50\),\(m<=10000\),最优解路径长度\(<=\) \(max\) \(long\) \(int\)。


首先,要确保自己的语文水平苟的住,这个鬼机器,每秒跑\(2^kkm\)的话是要跑刚好那么长的,不能多也不能少。

那么岂不是代表,只有长为\(2^kkm\)的链才算是有效边吗?

我们把所有有效边连上,跑最短路不就行了嘛。

如何求有效边?

\(2^k?\)有没有想到什么?

\(2^k=2^{k-1}+2^{k-1}?\)

对,就是倍增啊!

令\(g[u][v][j]\)代表点\(u\)到点\(v\)存在或不存在长度为\(2^j\)的边。

当\(g[u][k][j-1]\)和\(g[k][v][j-1]\)同时存在时,

\(g[u][v][j]\)存在。(\(k\)是枚举的一维)


#include <cstdio>#include <cstring>#include <queue>using namespace std;const int N=52;int g[N][N][70],n,m;//g[i][j][k]表示i点到j点存在边权为2^k的路int g0[N][N];int read(){    int x=0;char c=getchar();    while(c<'0'||c>'9') c=getchar();    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}    return x;}queue <int > q;int used[N],dis[N];void spfa(){    memset(used,0,sizeof(used));    used[1]=1;    memset(dis,0x3f,sizeof(dis));    dis[1]=0;    q.push(1);    while(!q.empty())    {        int u=q.front();        q.pop();        used[u]=0;        for(int v=1;v<=n;v++)            if(g0[u][v]&&dis[v]>dis[u]+g0[u][v])            {                dis[v]=dis[u]+g0[u][v];                if(!used[v])                {                    used[v]=1;                    q.push(v);                }            }    }}int main(){    memset(g,0,sizeof(g));    memset(g0,0,sizeof(g0));    n=read(),m=read();    int u,v;    for(int i=1;i<=m;i++)    {        u=read(),v=read();        g[u][v][0]=1;        //f[u][v][0]=v;    }    for(int j=1;j<=64;j++)        for(int k=1;k<=n;k++)            for(u=1;u<=n;u++)                for(v=1;v<=n;v++)                    if(g[u][k][j-1]&&g[k][v][j-1])                        g[u][v][j]=1;    for(u=1;u<=n;u++)        for(v=1;v<=n;v++)            for(int j=0;j<=64;j++)                if(g[u][v][j])                {                    g0[u][v]=1;                    break;                }    spfa();    printf("%d\n",dis[n]);    return 0;}

2018.5.2

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,492
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,493
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,132
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,295