洛谷 P1613 跑路 (倍增)

 学floyd的时候竟然没去想,这次傻了,枚举中间点的循环得放在最前面

    for(int t=1;t<=n;t++)
        
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                dis[i][j]=min(dis[i][j],(dis[i][t]+dis[t][j]));

这道题用的是倍增+floyd

dp[i][j][k]表示i到j的距离为2的k次方

dis[i][j]表示从i到j最少转移的次数


#include <bits/stdc++.h>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstdlib>
#include<map>
using namespace std;
typedef long long ll;
const int inf=9999999;
const long long int mod=1e9+7;
int n,m,u,v;
int dis[55][55];
bool dp[55][55][64];
void work()
{
    for(int t=0;t<64;t++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                    if(dp[i][j][t]&&dp[j][k][t])
                    {
                        dp[i][k][t+1]=true;
                        dis[i][k]=1;
                    }
}
void floyd()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
                dis[j][k]=min(dis[j][k],(dis[j][i]+dis[i][k]));
}
int main()
{
    memset(dp,false,sizeof(dp));
    for(int i=0;i<55;i++)
        for(int j=0;j<55;j++)
            dis[i][j]=inf;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        dp[u][v][0]=true;
        dis[u][v]=1;
    }
    work();
    floyd();
    printf("%d",dis[1][n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41758381/article/details/85859896
今日推荐