CSU——2161: 漫漫上学路 最短路
Description
众所周知,CSU(California State)University) 的上课地点距离学生公寓很远,对于爱睡懒觉的小Z来说,每天去上课就成了一件非常头疼的事,如果有早课的话更是如此。为了能让自己多睡一会,同时不至于上课迟到,小Z决定规划一条去新校的路线。
去新校的路上有很多条双向道路,每条道路连接了两个路口,且直接连接两个路口的道路只有一条,不存在一条道路的两端为同一个路口,每条道路都有一定的距离。同时道路两侧商铺众多,在提供了美食的同时也造成了一定程度的拥堵,在小Z心中每条道路都有一个拥堵值和美味值,且定义某条从学生公寓路口到新校路口的路线的拥堵值为其经过的道路的拥堵值之和,美味值为其经过道路的美味值之和。
因为起得晚,所以小Z没法去食堂买早餐,只能够顺路购买。小Z希望找到一条去新校最短的路线,如果存在多条总距离最短的路线,输出拥堵值最小的路线,如果拥堵值仍然相同,输出美味值最大的那条线路(小Z是个爱学习的好孩子,为了上课不迟到,有时只能狠心不吃美味的早餐了┭┮﹏┭┮)
Input
第一行为一个正整数 T ,代表数据组数(不超过 15 组)
第二行为两个正整数 n,m ,代表路口数和道路数(1≤n≤1000,n−1≤m≤n(n−1)/2)
其中 1 代表学生公寓路口, n 代表新校路口
之后 m 行,每行 5 个数 u,v,x,y,z
u,v 代表这条道路连接的两个路口,
x 代表这条道路的长度(1≤x≤1000 ),
y 代表这条道路的拥堵值(0≤y≤1000 ),
z 代表这条道路的美味值(0≤z≤1000 )。
Output
第一行输出三个正整r1,r2,r3 ,代表符合题意最优的那条路径的总距离,拥堵值和美味值
(数据保证总距离最小、拥堵值最小、美味值最大的路径是存在且唯一的)
接着顺序输出路径上经过的地点(以 1 开头,以 n 结束)
具体参见样例
Sample Input
1
4 6
1 2 1 3 5
2 4 2 2 0
1 4 3 6 2
2 3 4 5 3
1 3 1 2 4
3 4 2 3 2
Sample Output
3 5 6 1 3 4
思路:由题意我们可以知道我们要求的目的是求从1-n的条路径,这条路径满足总距离最小、拥堵值最小、美味值最大的路径,就相当于我们首先要求出总距离最小,在总距离最小的情况下求拥堵值最小,在总距离最小和拥堵值最小的情况下
求美味值最大,那么这题就是一个满足多个条件的最短路,我们可以使用dijkstra算法来写,dijkstra能够求出一点到任意一点的最短路径(正权情况下),就是模板上改动判断条件就行了。
可以看代码的注释理解一下。
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <queue>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn=10005;
int n,m;
struct Edge
{
int from,to,x,y,z;
Edge(int u,int v,int xx,int yy,int zz):from(u),to(v),x(xx),y(yy),z(zz){}
};
struct Node
{
int id,wx,wy,wz;
bool operator < (const Node& b) const//重载 < 符号,按照我们要求,优先级不同
{
if(wx==b.wx)
{
if(wy==b.wy)
return wz<b.wz;
else
return wy>b.wy;
}
else
return wx>b.wx;
}
};
bool vis[maxn];
int disx[maxn],disy[maxn],disz[maxn],order[maxn];//因为有三个权值,故开三个权值数组
vector<int>G[maxn];
vector<Edge>edge;
void init()
{
for(int i=0;i<=n;i++)
G[i].clear();
edge.clear();
memset(order,-1,sizeof(order));
}
void addedge(int f,int t,int aa,int bb,int cc)
{
edge.push_back(Edge(f,t,aa,bb,cc));
int si=edge.size();
G[f].push_back(si-1);
edge.push_back(Edge(t,f,aa,bb,cc));
si=edge.size();
G[t].push_back(si-1);
}
void dijkstra(int sta)
{
memset(vis,0,sizeof(vis));
priority_queue<Node>q;
for(int i=0;i<=n;i++)
disx[i]=disy[i]=disz[i]=INF;
disx[sta]=disy[sta]=disz[sta]=0;
q.push((Node){sta,0,0,0});
while(!q.empty())
{
Node temp=q.top();
q.pop();
int u=temp.id;
if(vis[u])
continue;
vis[u]=true;
int len=G[u].size();
for(int i=0;i<len;i++)
{
Edge& e=edge[G[u][i]];
if(disx[e.to]>disx[u]+e.x)//先求距离最小
{
disx[e.to]=disx[u]+e.x;
disy[e.to]=disy[u]+e.y;
disz[e.to]=disz[u]+e.z;
q.push((Node){e.to,disx[e.to],disy[e.to],disz[e.to]});
order[e.to]=u;
}
else if(disx[e.to]==disx[u]+e.x&&disy[e.to]>disy[u]+e.y)//距离相等求拥堵值最小
{
disy[e.to]=disy[u]+e.y;
disz[e.to]=disz[u]+e.z;
q.push((Node){e.to,disx[e.to],disy[e.to],disz[e.to]});
order[e.to]=u;
}
else if(disx[e.to]==disx[u]+e.x&&disy[e.to]==disy[u]+e.y&&disz[e.to]<disz[u]+e.z)//距离和拥堵值相等时求美味值最大
{
disz[e.to]=disz[u]+e.z;
q.push((Node){e.to,disx[e.to],disy[e.to],disz[e.to]});
order[e.to]=u;
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
init();
int u,v,a,b,c;
while(m--)
{
scanf("%d %d %d %d %d",&u,&v,&a,&b,&c);
addedge(u,v,a,b,c);
}
dijkstra(n);
printf("%d %d %d\n",disx[1],disy[1],disz[1]);
for(int i=1;i!=-1;i=order[i])
{
if(i==1)
printf("%d",i);
else
printf(" %d",i);
}
printf("\n");
}
return 0;
}
/**********************************************************************
Problem: 2161
User: jk1601zr
Language: C++
Result: AC
Time:964 ms
Memory:19812 kb
**********************************************************************/