hdoj 5636 Shortest Path

题目

        如果不考虑6个特殊点,两点间距离就是下标差。但是这6个点的存在有可能缩短了两点间距离,所以跑一下6个点到所有点的最短路(6*6*n的floyd),对于每个询问,算一下直接s-t和s-6个点中的某个-t的最小值即可。

#include <iostream>  
#include <stdio.h>  
#include <cmath>  
#include <algorithm>  
#include <string>  
#include <memory.h>  
#include <vector>  
#include <queue>  
#include <stack> 

using namespace std;

#define ll long long

int dis[6][100010];

int a[6];

void ckMin(int &a,int b){
    if(b<a){
        a=b;
    }
}

void ckMin(ll &a,ll b){
    if(b<a){
        a=b;
    }
}

const ll mod = 1e9+7;

int main(){
    
    
    int t;
    cin>>t;
    
    while(t--){
        int n,m;
        cin>>n>>m;
        for(int i=0;i<6;i++){
            cin>>a[i];
            for(int j=1;j<=n;j++){
                dis[i][j] = j-a[i];
                if(dis[i][j]<0){
                    dis[i][j] = -dis[i][j];
                }
            }
        }
        
        ckMin(dis[0][a[1]],1);
        ckMin(dis[1][a[0]],1);
        ckMin(dis[2][a[3]],1);
        ckMin(dis[3][a[2]],1);
        ckMin(dis[4][a[5]],1);
        ckMin(dis[5][a[4]],1);
        
        for(int k=0;k<6;k++){
            for(int i=0;i<6;i++){
                for(int j=1;j<=n;j++){
                    ckMin(dis[i][j],dis[i][a[k]]+dis[k][j]);
                }
            }
        }
        
        ll ans = 0;
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            ll tmp=abs(u-v);
            for(int j=0;j<6;j++){
                ckMin(tmp,abs(u-a[j])+dis[j][v]);
            }
            ans += tmp*i;
            ans%=mod;
        }
        cout<<ans<<endl;
    }
    
    return 0;
}


你可能感兴趣的:(floyd)