CCF-201712-4

2017-12-4CCF行车路线
//https://github.com/GLAster/ccf-csp/blob/master/201712-4%20%E8%A1%8C%E8%BD%A6%E8%B7%AF%E7%BA%BF%20ccf.cpp

#include <bits/stdc++.h>
using namespace std;
typedef long long llt;
const llt inf=0x7fffffffffffffff;
llt sA[512][512],bA[512][512];
llt n,m;
llt sqe(llt x){return x*x;}//返回平方
llt dijkstra(){
    bool visitsr[512]={0},visitbr[512]={0};
    vector<llt> sr(sA[0],sA[0]+n),br(bA[0],bA[0]+n),presr(n,inf);
    for(llt i=0;i<n;++i){
        if(sr[i]<inf){
            presr[i]=sr[i];
            sr[i]*=sr[i];
        }
    }
    visitsr[0]=visitbr[0]=1;
    while(true){
        llt minval=inf,u=-1,flag=0;
        for(llt i=0;i<n;++i){//找到一条最短路径,并且用flag标记是大路还是小路
            if(!visitbr[i]&&minval>br[i]){
                minval=br[u=i];
                flag=0;//大路
            }
            if(!visitsr[i]&&minval>sr[i]){
                minval=sr[u=i];
                flag=1;//小路
            }
        }
        if(u==-1)break;
        if(flag==1) visitsr[u]=1;
        else visitbr[u]=1;
        for(llt w=0;w<n;++w){
            if(!visitsr[w]&&sA[u][w]<inf){//从u到w存在一条小路
				if(flag==1){//u前驱是小路
                    llt len=sr[u]-sqe(presr[u])+sqe(presr[u]+sA[u][w]);
                    if(sr[w]>len||(sr[w]==len&&presr[w]>presr[u]+sA[u][w])){
                        sr[w]=len;
                        presr[w]=presr[u]+sA[u][w];
                    }
                }else{//u前驱是大路
                    llt len=br[u]+sqe(sA[u][w]);
                    if(sr[w]>len||(sr[w]==len&&presr[w]>sA[u][w])){
                        sr[w]=len;
                        presr[w]=sA[u][w];
                    }
                }
            }
            if(!visitbr[w]&&bA[u][w]<inf){//从u到w存在一条大路
                if(flag==1){//u前驱是小路
                    llt len=sr[u]+bA[u][w];
                    br[w]=min(len,br[w]);
                }else{//u前驱是大路
                    llt len=br[u]+bA[u][w];
                    br[w]=min(len,br[w]);
                }
            }
        }
    }
    return min(sr[n-1],br[n-1]);
}
int main(){
    scanf("%lld %lld",&n,&m);
    for(llt i=0;i<n;++i){
        for(llt j=0;j<n;++j){
            sA[i][j]=sA[j][i]=inf;
            bA[i][j]=bA[j][i]=inf;
        }
    }
    for(llt i=0;i<m;++i){
        llt t,a,b,c;
        scanf("%lld %lld %lld %lld",&t,&a,&b,&c);
        --a,--b;
        if(t==1) sA[a][b]=sA[b][a]=min(c,sA[a][b]);
        else bA[a][b]=bA[b][a]=min(c,bA[a][b]);
    }
    llt ret=dijkstra();
    printf("%lld\n",ret);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值