The Shortest Path in Nya Graph HDU - 4725 最短路,SPFA算法+优先队列,网络层加虚拟点
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
Help us calculate the shortest path from node 1 to node N.
InputThe first line has a number T (T <= 20) , indicating the number of test cases.
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.OutputFor test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
If there are no solutions, output -1.Sample Input
2 3 3 3 1 3 2 1 2 1 2 3 1 1 3 3 3 3 3 1 3 2 1 2 2 2 3 2 1 3 4
Sample Output
Case #1: 2 Case #2: 3
题意:给定一幅有层次的线路图,第一行输入 N,M,C 表示 N 个点和 M条边,每两层之间通过的费用是 C。
意思就是,除了走给定的路之外,我们还可以选择穿透层次,花费 C 的费用走到上一层或者下一层的任意一个节点,而不去走题目给定的边。
然后第二行 N个数就是表示第 i 个节点的层号,然后 M 行是描述边的。
思路:由于数据太大,一次可以设想每层都有一个入口和出口,层内的点到出口的距离为0,同样入口也是,层与层之间通过
让每层只出不进的出口连接上下两层只进不出的入口,权值是c,层内点与点之间的初始距离为无穷,有额外边的为额外值。
这样有N个初始的点,外加N个入口和N个出口,总共有3*N个点,边的数量也要变大。我将第N+1到2*N的点设为出口,将2*N+1到3*N之间的点
设为入口,具体内容见代码。
代码:
1 #include <cstdio> 2 #include <fstream> 3 #include <algorithm> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <string> 9 #include <cstring> 10 #include <map> 11 #include <stack> 12 #include <set> 13 #include <sstream> 14 #include <iostream> 15 #define mod 998244353 16 #define eps 1e-6 17 #define ll long long 18 #define INF 0x3f3f3f3f 19 using namespace std; 20 21 //数据开到比n*3要大 22 const int maxn = 1000005; 23 //结构体定义边的信息 24 struct node1 25 { 26 int y,z,next; 27 }; 28 node1 no[maxn]; 29 //结构体定义为优先结构 30 struct node2 31 { 32 //x表示当前点,len表示从起点到x的权值 33 int x,len; 34 friend bool operator < (node2 a,node2 b) 35 { 36 return a.len>b.len; 37 } 38 }; 39 //t表示测试样例数,n表示点数,m表示额外边数,p表示层与层之间的权值 40 int t,n,m,p; 41 //存放边的位置 42 int head[maxn]; 43 //存放起点到其他点的最短距离 44 int dis[maxn]; 45 //标记是否为最短点 46 bool vis[maxn]; 47 //表示边的数量 48 int s; 49 //函数用于储存边的信息 50 //表示从x到y的权值为z 51 void add(int x,int y,int z) 52 { 53 no[s].y=y; 54 no[s].z=z; 55 no[s].next=head[x]; 56 head[x]=s++; 57 } 58 //初始化层与层之间入口与出口的连接 59 //a表示层数,b表示层之间的权值 60 void init(int a,int b) 61 { 62 add(a+1,2*n+2,b); 63 for(int i=2;i<n;i++) 64 { 65 add(n+i,2*n+i-1,b); 66 add(n+i,2*n+i+1,b); 67 } 68 add(2*n,3*n-1,b); 69 } 70 //函数求最短路 71 void spfa() 72 { 73 //定义优先队列 74 priority_queue<node2> qu; 75 node2 q; 76 //初始化数据 77 memset(vis,0,sizeof(vis)); 78 memset(dis,INF,sizeof(dis)); 79 dis[1]=0; 80 q.x=1; 81 q.len=0; 82 //起点为1,权值为0 83 qu.push(q); 84 while(!qu.empty()) 85 { 86 q=qu.top(); 87 qu.pop(); 88 //如果当前点已找过,则无需再找 89 if(vis[q.x]) 90 { 91 continue; 92 } 93 //标记此点已找过 94 vis[q.x]=1; 95 //遍历此点连接的边 96 for(int i=head[q.x];i!=-1;i=no[i].next) 97 { 98 int u=no[i].y; 99 int v=no[i].z; 100 //更新起点到u的最小值 101 if(dis[u]>dis[q.x]+v) 102 { 103 dis[u]=dis[q.x]+v; 104 //将此点入队 105 node2 s; 106 s.x=u; 107 s.len=dis[u]; 108 qu.push(s); 109 } 110 } 111 } 112 } 113 int main() 114 { 115 scanf("%d",&t); 116 //ans表示测试的第几个样例 117 int ans=1; 118 while(t--) 119 { 120 s=1; 121 memset(head,-1,sizeof(head)); 122 scanf("%d %d %d",&n,&m,&p); 123 //初始化层 124 init(n,p); 125 int a,b,c; 126 //初始化点与层之间的权值 127 for(int i=1;i<=n;i++) 128 { 129 scanf("%d",&a); 130 add(i,a+n,0); 131 add(a+2*n,i,0); 132 } 133 //初始化点与点之间的权值 134 for(int i=1;i<=m;i++) 135 { 136 scanf("%d %d %d",&a,&b,&c); 137 add(a,b,c); 138 add(b,a,c); 139 } 140 spfa(); 141 printf("Case #%d: ",ans++); 142 //判断是否有解 143 if(dis[n]!=INF) 144 { 145 printf("%d\n",dis[n]); 146 } 147 else 148 { 149 printf("-1\n"); 150 } 151 } 152 }
原文地址:https://www.cnblogs.com/mzchuan/p/11567580.html
- mysql密码遗忘和登陆报错问题
- 新一轮发展趋势:城市智能化已经势不可挡
- Enterprise Library 4.1学习笔记2----数据访问程序块
- 微信小程序中用户唯一ID的获取
- Mysql备份系列(2)--mysqldump备份(全量+增量)方案操作记录
- Enterprise Library 4.1学习笔记1----配置应用程序块(c/s和b/s均适用)
- 简单账本-用完即走的微信小程序
- 新技术革命和新产业变革正进行 “互联网+大数据+人工智能+”时代正到来
- 微信小程序开发及相关设置小结
- gitlab两种连接方式:ssh和http配置介绍
- C#实现微信AES-128-CBC加密数据的解密
- UrlReferrer为空的问题?
- DeepMind发文回顾2017:AlphaGo团队已迎战下一个重大挑战
- [你必须知道的.Net]读书笔记--浅clone与深clone
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 什么是时间分片(Time Slicing)?
- 逐行分析鸿蒙系统的 JavaScript 框架
- 48张小图带你领略Flex 布局之美
- 怎样设计一个 JavaScript 插件系统
- 一道 React 面试题:在浏览器、组件和元素中都渲染了些什么?
- 「新手入门福利」一张脑图带你掌握Git命令
- LeetCode | 58.最后一个单词的长度
- 模拟面试,解锁大厂 ——从Android的事件分发说起
- scRepertoire||单细胞免疫组库分析:R语言应用(一)
- Docker体验(二) - 自建Image
- 小程序代码复用 - template
- 五. Spring Security 权限管理
- 文档驱动 —— 表单组件(五):基于Ant Design Vue 的表单控件的demo,再也不需要写代码了。 表单一 公司信息表单二 员工信息,简化版,只是为了演示表单的切换。以后会出
- 文档驱动 —— 查询组件:将查询功能做到极致!你说还有啥没包含进来?antdv + vue 3.0 全新体验 快捷查询个性化查询方案更换各种查询方式更多的查询条件meta 驱动封装基础
- ES6能干啥?