hdu5636 Shortest Path BestCoder题目

这道题 一开始不愿意去动笔 比如有大牛写了几十个判断 也是可以A的 
因为对于起点s,终点e,这道题的答案要么就是abs(e-s),要么就是受到了
加入的三条边的影响
我们只要对这6个点每个点进行一遍spfa 然后查询的时候 执行6次 
s到6个点的距离加上这个点到e的距离  这样的距离肯定是最短的
因为这6个点之中的点到e的距离都是你实现跑最短路求出来的
把这6种情况的答案和abs(e-s)比较  最小的就是我们求得答案

代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef __int64 ll;
const int inf=0x3f3f3f3f;
const int maxn=100005;
inline void swap(int &xx,int &yy){
    int temp=xx;
    xx=yy;
    yy=temp;
}
int n,m;
int a1,b1,a2,b2,a3,b3;
const ll mod=1000000007;
int dis[7][maxn];
vector<int> a[maxn];
void add(int x,int y){
    a[x].push_back(y);
    a[y].push_back(x);
}
typedef pair<int,int> p;
bool used[maxn];
inline int min(int xx,int yy){
    return xx>yy?yy:xx;
}
template<class value_type_>
void scanf_(value_type_ &data){
    data=0;
    char t;
    while((t=getchar())&&(t<'0'||t>'9')){}
    do{
        data=data*10+(t-'0');
        t=getchar();
    }while(t<='9'&&t>='0');
}
int arr[7];
void bfs(int s){
    queue<int>que;
    while(!que.empty()){
        que.pop();
    }
    memset(used,false,sizeof(used));
    que.push(arr[s]);
    used[arr[s]]=true;
    dis[s][arr[s]]=0;
    while(!que.empty()){
        int p2=que.front();
        que.pop();
        used[p2]=false;
        for(int i=0;i<a[p2].size();i++){
            int dx=a[p2].at(i);
            if(dis[s][dx]>dis[s][p2]+1){
// printf("push %d %d\n",dx,d+1);
                dis[s][dx]=dis[s][p2]+1;
                if(!used[dx]){
                    que.push(dx);
                    used[dx]=true;
                }
            }
        }
    }

}
inline ll min_(ll xx,ll yy){
    return xx>yy?yy:xx;
}
inline ll abs_(ll xx){
    if(xx<0ll)return -xx;
    return xx;
}
int main(){
    int T;
    #ifdef ONLINE_JUDGE
    #else
    freopen("in.txt","r",stdin);
    freopen("ac.txt","w",stdout);
    #endif // ONLINE_JUDGE
ios::sync_with_stdio(false);
    scanf_(T);
    while(T--){
        cin>>n>>m;
        cin>>a1>>b1>>a2>>b2>>a3>>b3;

        for(int i=0;i<maxn;i++)
        a[i].clear();
        for(int i=1;i<n;i++){
            a[i].push_back(i+1);
            a[i+1].push_back(i);
        }
        if(a1>b1){
            swap(a1,b1);
        }if(a1!=b1) add(a1,b1);
        if(a2>b2){
            swap(a2,b2);
        }if(a2!=b2) add(a2,b2);
        if(a3>b3){
            swap(a3,b3);
        } if(a3!=b3) add(a3,b3);
        arr[0]=a1;
        arr[1]=b1;
        arr[2]=a2;
        arr[3]=b2;
        arr[4]=a3;
        arr[5]=b3;
        memset(dis,inf,sizeof(dis));
        for(int i=0;i<6;i++)
            bfs(i);
        ll ans=0;
        ll coun=0;
        while(m--){
            int s,e;
            scanf_(s);
            scanf_(e);
            if(s>e)swap(s,e);
            coun++;
            if(s==e)continue;
            ll tp=(ll)(e-s);
            for(int i=0;i<6;i++){
               tp=min_((ll)(abs_((ll)(arr[i]-s))+dis[i][e]),tp);
// tp=min_((ll)(abs_(ll(arr[i]-e))+dis[i][s]),tp);
            }
            ans=ans+tp*coun;
            ans%=mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

这样的代码可不可以优化
我也想了
比如只跑三遍spfa 就是只对加入的边的终点跑spfa
这样可不可以?
hdu5636 Shortest Path BestCoder题目_第1张图片

如果我们只是计算到起点的情况
我们发现这个图上的情况就是ans=abs(e-s)
但是,有没有更短的?
当然 直接走2和1 会更短 但是是从终点走过去的
所以我们不能忽略终点的情况
当然,可能我说的不对 希望大牛指教
毕竟这是一道水题

你可能感兴趣的:(hdu5636 Shortest Path BestCoder题目)