试题编号: | 201712-4 |
试题名称: | 行车路线 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 小明和小芳出去乡村玩,小明负责开车,小芳来导航。 输入格式 输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。 输出格式 输出一个整数,表示最优路线下小明的疲劳度。 样例输入 6 7 样例输出 76 样例说明 从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。 数据规模和约定 对于30%的评测用例,1 ≤ n ≤ 8,1 ≤ m ≤ 10; |
就是Dijkstra算法的变形,需要一个附加数组pre[u],来记录与u相连的连续小路的C(公里)的总和。具体看图和代码。
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<unordered_map>
#include<set>
#include<sstream>
using namespace std;
const int MAXN = 505;
const int INF = 9999999;
struct Node{
int v;
long long w;
int type;
Node(int v,long long w,int type){
this->v = v;
this->w = w;
this->type = type;
}
};
/*
** 用于堆优化的结构体
*/
struct Pri{
int u;
int dis;
Pri(int u,int dis){
this->u = u;
this->dis = dis;
}
bool operator<(const Pri &pri) const {
return this->dis > pri.dis;
}
};
vector<Node> adj[MAXN];
long long dis[MAXN];
bool vis[MAXN] = {false};
priority_queue<Pri> choose;
long long pre[MAXN] = {0};//pre[u]=10表示与u节点相连的连续小路C的总和为10(总公里数为10)
//这里的连续小路必须连接u,并不是到达u之前所有小路c(公里)的总和,而是与u相连的连续小路c(公里)的总和。
void Dijkstra(int s,int n){
fill(dis,dis+n+1,INF);
dis[s] = 0;
choose.push(Pri(s,dis[s]));
for(int i=1;i<=n;i++){
int u = -1;
/*
** 下面的代码为堆优化代码,这道题不适用堆优化也行。
*/
do{
if(!choose.empty()){
const Pri pri = choose.top();
u = pri.u;
choose.pop();
}
}while(vis[u]);
vis[u] = true;
for(int j=0;j<adj[u].size();j++){
int v = adj[u][j].v;
int w = adj[u][j].w;
int t = adj[u][j].type;
if(!vis[v]){
if(t== 1){ //如果这条道路是条小道
/*
**从u到达v的疲劳度就等于,到达u的疲劳度dis[u]减去之前连续小路的疲劳度
**pre[u]*pre[u],再加上之前的连续小路和这段小路组成的新连续小路的疲劳度
**(pre[u]+w)*(pre[u]+w)。
*/
long long len = dis[u] - pre[u]*pre[u] + (pre[u]+w)*(pre[u]+w);
if(dis[v] > len) {
dis[v] = len;
pre[v] = pre[u] + w;
choose.push(Pri(v,dis[v]));
}
}else{ //如果这条道路是条大道
if(dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
pre[v] = 0;
choose.push(Pri(v,dis[v]));
}
}
}
}
}
}
int main(){
int n,m;
int t,a,b,c;
long long cost;
cin>>n>>m;
while(m--){
cin>>t>>a>>b>>c;
adj[a].push_back(Node(b,c,t));
adj[b].push_back(Node(a,c,t));
}
Dijkstra(1,n);
cout<<dis[n]<<endl;
return 0;
}