shuoj1900 小6爱夜跑
2015-11-28 15:53
267 查看
Description
![](http://202.121.199.212/JudgeOnline/upload/201505/7.png)
自从小6学了最短路算法之后,就成了一个不折不扣的最短路理论拥护者,每次在校园里夜跑的时候,只要确定好起点和终点他就能快速算出最短的路径。然而小6却没有走过每一条路,只是对这些路径长度做了一个粗略估计,于是每条路就有了估计值与实际值的差距。小6想要知道从起点到终点,按照其中任意一条预估的最短路径跑,实际最长可能需要走过的路程。(因为同一长度的最短路可能有多个)
Input
多组输入,第一行是一个整数T,表示输入数据的组数(T≤20)。接下来有T组数据,每组数据的第一行是四个整数N、M、S、E,分别代表图中的顶点数、边数、起点编号和终点编号。
(2≤N≤100, 1≤M≤1000, 1≤S,T≤N, S≠T)
之后的M行每行有四个整数u, v, a, b,代表图中编号为u的点到编号为v的点有一条双向边。
每条边有两个值a、b分别代表这条边的估计长度与实际长度。
(1≤u,v≤N, 1≤a,b≤1000, u ≠ v)
数据保证两个顶点间至多只有一条双向边相连,起点与终点间必定存在通路。
Output
对于每组输入,输出一行两个整数并换行,表示小6估算出的最短路长度以及实际最长可能需要走过的路程,两个整数间有一个空格。Sample Input
22 1 1 2
1 2 3 4
3 3 1 3
1 2 2 3
1 3 3 4
2 3 1 2
Sample Output
3 43 5
分析:
本题是个最短路问题,用priority_queue优化的dijkstra算法,dijkstra利用了最优子结构的思想求最短路,不过在此基础上做了演变,所求的是起点到终点的预估长度(最短路)和实际长度(“最长路”),最长路并不是完全意义上的最长路,题干中表明了实际距离是在选取了任意一个预估距离之后的其中最长距离,“最长路”即是在多条最短路中的最长路,用dis[x]表示起点到各点的最短路,res[x]表示最长路。也是在帮助之下才完全想明白,即在更新最短路dis[y]时,最长路res[y]是不受影响的,和dis[x]一样进行更新,只有直到出现了相同最短路即(dis[y]==dis[x]+d)的时候,才选取其中距离较长的更新res[y].
代码:
#include <bits/stdc++.h> #define PB(x) push_back(x) #define MP(a,b) make_pair(a,b) #define INF 0x3FFFFFFF using namespace std; typedef pair<int,int> PII; typedef vector<PII> VII; typedef pair<pair<int,int>,int> PIII; typedef vector<PIII> VIII; //用vector存图 const int MAXN = 100010; VIII G[MAXN]; void add_edge(int u,int v,int d,int w){ G[u].PB(MP(MP(v,d),w)); //表示点u到点v的预估距离为d,实际距离为w } void init(int n){ //初始化清零 for(int i=0;i<n;i++){ G[i].clear(); } } int vis[MAXN]; //记录访问过的边 int dis[MAXN]; //记录最短路 int res[MAXN]; //记录最长路 void dijkstra(int s,int n){ for(int i=0;i<n;i++)vis[i] = 0; for(int i=0;i<n;i++)dis[i] = (i == s ? 0 : INF); //每次求最短,初始值设为最大 for(int i=0;i<n;i++)res[i] = (i == s ? 0 : -1); //每次求最长,初始值设为负 //优先队列优化,dis[s]在前保证每次距离最小的点在顶,优先更新最短距离的点,充分利用优先子结构的性质。 priority_queue<PII,VII,greater<PII> >q; q.push(MP(dis[s],s)); while(!q.empty()){ PII p = q.top(); int x = p.second; q.pop(); if(vis[x]) continue; //访问过的点不再访问 vis[x] = 1; //取出起点x对应的所有终点y,分别更新预估距离d和实际距离w for(int i=0;i<G[x].size();i++){ int y = G[x][i].first.first; int d = G[x][i].first.second; int w = G[x][i].second; if(!vis[y] && dis[x] + d < dis[y]){ //若当前最短距离能被更新,同时更新dis,res数组 dis[y] = dis[x] + d; res[y] = res[x] + w; // res[y] = max(res[y],res[x]+w); // cout<<res[y]<<endl; q.push(MP(dis[y],y)); } if(!vis[y] && dis[x]+d==dis[y]){ //只有出现相同最短路径时,才取较长的实际距离更新res数组 res[y]=max(res[y],res[x]+w); } } } } int main(int argc, char** argv) { int t; scanf("%d",&t); while(t--){ int n,m,s,t; scanf("%d%d%d%d",&n,&m,&s,&t); init(n); while(m--){ int u,v,d,b; scanf("%d%d%d%d",&u,&v,&d,&b); u--;v--; //下标从0开始 add_edge(u,v,d,b); add_edge(v,u,d,b); } dijkstra(s-1,n); cout<<dis[t-1]<<' '<<res[t-1]<<endl; } return 0; }
相关文章推荐
- 浅谈C++多态性 http://blog.csdn.net/hackbuteer1/article/details/7475622
- 单例类的使用方法
- 初步了解JPA
- java 中常见异常
- 1-3-13:反向输出一个三位数
- 什么是单态模式
- —————————————1005————找规律的思想值得学习。
- UIWebview 适配 计算webview高度
- leetcode-dungeon-game
- 41.Android aapt工具
- asp.net实现输出xml的方法
- 选择图片
- java加载文件路径问题
- Spring声明式事务管理(基于注解的方式)
- angular实现两个select选择框互相传值
- HTML文本去除标签
- 正则表达式
- Remove Duplicates from Sorted List
- CCBPM节点访问规则与绑定人员的联系
- CodeForces 598D Igor In the Museum 暴力