问题描述
思路
- 设置结构体,包括类型、目的地、长度、疲劳值,具体的意义可往下看下代码注释
- 使用迪杰斯特拉算法,更新路径时分为3种情况,1 原来最后一条路是大路 2 原来最后一条路是小路,新加入的是小路 3 原来最后一条路是小路,新加入的是大路,每种情况代码中都写了注释,不懂的可以评论提问哦~
- 输入到n结点的疲劳值!
提醒
要注意疲劳值是会产生溢出的,所以要使用long long ,我原来用int,一直80分,后来改long long试了下,就100了!
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct r{
int t;//类型 1 小路 0大路
long long a; // roads中是道路的目的地,res中是连续的小道长度
long long c;//长度
long long p; // 连续小道产生的疲劳值
r(int tt,long long aa,long long cc):t(tt),a(aa),c(cc){} //roads时用这个初始化函数
r(int tt,long long cc,long long a,long long pp):t(tt),c(cc),p(pp){} //res时用这个初始化函数
r(){}
};
//vector<road> roads;
vector<r> roads[503]; // 记录道路
r res[503]; // 记录结果数组
bool vis[503]; //是否被访问过
int t,a,b,c;
void dij(){
for(int i = 1;i<=n;i++){
int min = 100005;
int index = -1;
for(int j = 1;j<=n;j++){ // 寻找最近的一个点
if(!vis[j]&&res[j].c<min){
index = j;
min = res[j].c;
}
}
if(index == -1 || index == n)
return;
vis[index] = true;
for(int j=0;j<roads[index].size();j++){
r temp = roads[index][j];
if(vis[temp.a])
continue;
if(temp.t==1){// 是小道
if(res[index].t==1){
// 前面也是小道时
long long len = res[index].a; // 以前连续的小道长度
len += temp.c; // 加上这次的小道长度
long long new_p = len*len; //计算新的因为连续小道产生的疲劳值
if(res[index].c+ new_p - res[index].p < res[temp.a].c){ // 比较疲劳值 ,要先减去旧的连续小道疲劳值,再加上新的小道疲劳值
res[temp.a].c = res[index].c+new_p -res[index].p;
res[temp.a].t = 1; // 最后一个路是小道
res[temp.a].p = new_p; //连续的小道长度产生的疲劳值
res[temp.a].a = len; // 更新连续的小道长度
//printf("%d %d %d\n",temp.a,res[temp.a].c,res[temp.a].a);
}
}else{//前面是大道时
if(res[index].c+temp.c*temp.c < res[temp.a].c){ //比较疲劳值
res[temp.a].c = res[index].c+temp.c*temp.c; //更新 和上面原理一样
res[temp.a].t = 1;
res[temp.a].p = temp.c*temp.c;
res[temp.a].a = temp.c;
}
}
}else{//是大道
if(res[index].c+temp.c < res[temp.a].c){ // 大道就简单了
res[temp.a].c = res[index].c+temp.c;
res[temp.a].t = 0;
res[temp.a].p = 0;
res[temp.a].a = 0;
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
while(m--){
scanf("%d%d%d%d",&t,&a,&b,&c);
roads[a].push_back(r(t,b,c));
roads[b].push_back(r(t,a,c));
}
for(int i = 1;i<=n;i++){
res[i] = r(0,100005,0,0);
}
res[1].c = 0;
dij();
printf("%d",res[n].c);
return 0;
}