比赛 20150422 评测结果 AAAAAAAAAAA
题目名称 背驮式行走 最终得分 100
用户昵称 ztx 运行时间 0.043 s
代码语言 C++ 内存使用 1.57 MiB
提交时间 2015-04-22 10:41:08
显示代码纯文本
/****************************************\
* Author : ztx
* Title  : [bzoj] 3891: [Usaco2014 Dec]Piggy Back
[cogs] 1944 背驮式行走
* ALG    : 最短路
* CMT    : 三次最短路 。。 水 
* Time   :
\****************************************/
 
#include <cstdio>
 
int CH , NEG ;
inline void read(int& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}
 
#include <deque>
#include <cstring>
#include <algorithm>
 
#define  maxn  40010LL
#define  maxm  40010LL
#define  infi  0x7f7f7f7fLL
 
struct FST { int to , next ; } e[maxm<<1] ;
int star[maxn] = {0} , tote = 1 ;
void AddEdge(int u , int v) {
    e[++tote].to = v ; e[tote].next = star[u] ; star[u] = tote ;
}
 
std::deque<int>q ;
bool exist[maxn] = {0} ;
int dis[3][maxn] = {0} ;
 
inline void SPFA(int o , int w , int u) {
int v , p ;
    dis[o][u] = 0 ;
    q.push_back(u) ;
    while (!q.empty()) {
        u = q.front() , q.pop_front() , exist[u] = false ;
        for (p = star[u] ; p ; p = e[p].next) {
            if (v=e[p].to , dis[o][v]>dis[o][u]+w) {
                dis[o][v] = dis[o][u]+w ;
                if (!exist[v]) {
                    exist[v] = true ;
                    if (!q.empty() && dis[o][v]<=dis[o][q.front()]) q.push_front(v) ;
                    else q.push_back(v) ;
                }
            }
        }
    }
}
 
int B , E , P , N , M ;
int ans = infi ;
 
int main() {
int i , u , v ;
    #define READ
    #ifdef  READ
        freopen("piggyback.in" ,"r",stdin ) ;
        freopen("piggyback.out","w",stdout) ;
    #endif
    memset(dis , 0x7f , sizeof dis) ;
    read(B) , read(E) , read(P) , read(N) , read(M) ;
    for (i = 1 ; i <= M ; i ++ ) {
        read(u) , read(v) ;
        AddEdge(u , v) ;
        AddEdge(v , u) ;
    }
    SPFA(0 , B , 1) ;
    SPFA(1 , E , 2) ;
    SPFA(2 , P , N) ;
    for (i = 1 ; i <= N ; i ++ )
        if ((dis[0][i]!=infi)&&(dis[1][i]!=infi)&&(dis[2][i]!=infi))
            ans = std::min(ans , dis[0][i]+dis[1][i]+dis[2][i]) ;
    printf("%d\n", ans) ;
    #ifdef  READ
        fclose(stdin) ; fclose(stdout) ;
    #else
        getchar() ; getchar() ;
    #endif
    return 0 ;
}