P1613 跑路

来源:互联网 发布:日本留学的好专业知乎 编辑:程序博客网 时间:2024/06/15 15:25

传送门
刚开始眼瞎,看成了跑2^k米。。。。。。。
智障的我:这不就是个最短路吗…….
忽然发现:你这不是放屁吗,如果正好公司和家差4千米,这样1秒就跑完了。。。。。
这可咋办呢
正解 : DP+倍增(心情复杂)
f[i][j][k]表示j,k的距离是2^i次方,那么这两个点便可以1秒到达
问题是咋求呢
如果f[i-1][j][k]与f[i-1][k][v]都为真,那么f[i][j][v]就为真
为啥呢,其实就等于一个人分两秒的时间先从j->k再从k->v,这样j,v之间的长度就是符合2^k
就可以1秒到达,这样求出可以1秒到达的两两点,然后跑floyd就可以了(n<=50)
需要注意的是floyd赋初值时要写127/3,或者是直接赋值65(maxlong<=2^65-1)
赋值成maxint容易在floyd的权值变化时出现溢出的情况,从而搞出负数,从而WA!

#include <iostream>#include <cstdio>#include <cstring>using namespace std;bool f[65][51][51];int map[51][51];int main(){    int n,m;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)     for(int j=1;j<=n;j++)      map[i][j]=65;    for(int i=1;i<=m;i++)    {        int x,y;        scanf("%d%d",&x,&y);        f[0][x][y]=1;        map[x][y]=1;    }    for(int i=1;i<=64;i++)     for(int j=1;j<=n;j++)      for(int k=1;k<=n;k++)       for(int l=1;l<=n;l++)        if(f[i-1][j][k]&&f[i-1][k][l])         f[i][j][l]=1,map[j][l]=1;    for(int i=1;i<=n;i++)     for(int j=1;j<=n;j++)      for(int k=1;k<=n;k++)       map[j][k]=min(map[j][k],map[j][i]+map[i][k]);    printf("%d",map[1][n]);     return 0;}
原创粉丝点击