dijkstra的stl实现(最近觉得挺方便的
dijkstra的stl实现(最近觉得挺方便的
stl可作为跳板
--- Rujia liu
struct node {
int dis, id;
node(int dis = 0, int id = 0) : dis(dis), id(id) {}
bool operator < (const node& xx) const {
return dis > xx.dis;
}
};
struct Edge{
int x,y,val;
Edge(int x = 0, int y = 0, int val = 0) : x(x), y(y), val(val) {}
};//弧
//以下为vector版
struct Dijkstra {
int n,m;
vector<Edge> edges;// 边列表
vector<int> G[MAXN];// 每个节点出发的边的编号(从0开始
bool vis[MAXN];
int d[MAXN];//s 到各点距离
int p[MAXN];// 最短路上的一条边
void init(int n) {
this->n = n;
for(int i = 0; i < n; i++) G[i].clear() ;
edges.clear() ;
}
void add_edge(int x, int y, int val) {
edges.push_back((Edge){x, y, val});//没有构造函数的写法
m = edges.size() ;
G[x].push_back(m-1);
}
void dijkstra (int s) {
priority_queue <node> q;
for(int i = 0; i < n; i++) d[i] = INF;
d[s] = 0;
memset(vis, 0, sizeof(vis));
q.push(node(0,s));//注意id与dis的顺序哦(别问我是怎么知道的
while(!q.empty() ) {
node tmp = q.top() ; q.pop() ;
int u = tmp.id ;
if(vis[u]) continue;
vis[u] = true;
for(int i = 0;i < G[u].size() ; i++) {
Edge& e = edges[ G[u][i] ];//引用不加也行
if(d[e.y] > d[u] + e.val ) {
d[e.y ] = d[u] + e.val ;
p[e.y ] = G[u][i];
q.push(node(d[e.y], e.y)) ;
}
}
}
}
};
用stl+dij实现的应用 & 题目
要求输出路径的
统计任意两点之间的路径(包括起点&终点)
代码呢,就是上面的
...
p[e.y ] = G[u][i];
...
//在struct Dji...里面加
// dist[i]为s到i的距离,paths[i]为s到i的最短路径(经过的结点列表,包括s和t)
void GetShortestPaths(int s, int* dist, vector<int>* paths) {
dijkstra(s);
for(int i = 0; i < n; i++) {
dist[i] = d[i];
paths[i].clear();
int t = i;
paths[i].push_back(t);
while(t != s) {
paths[i].push_back(edges[p[t]].from);
t = edges[p[t]].from;
}
reverse(paths[i].begin(), paths[i].end());
}
}
题意: 在一张图中有两种路线,一种是经济线,一种是商业线,经济线可以随便走,但是商业线只能走一次。现在问从起点到终点的最短路是什么。
注意: 商业线也是双向的
// 题目相关(一开始写的丢了,只能去代码仓库找了...)
//作者: Rujia Liu
Dijkstra solver;
int d1[maxn], d2[maxn];
vector<int> paths1[maxn], paths2[maxn];
int main() {
int kase = 0, N, S, E, M, K, X, Y, Z;
while(scanf("%d%d%d%d", &N, &S, &E, &M) == 4) {
solver.init(N);
S--; E--; // 编号从0~N-1
for(int i = 0; i < M; i++) {
scanf("%d%d%d", &X, &Y, &Z); X--; Y--;
solver.AddEdge(X, Y, Z);
solver.AddEdge(Y, X, Z);
}
solver.GetShortestPaths(S, d1, paths1); // S到所有点的距离和路径
solver.GetShortestPaths(E, d2, paths2); // T到所有点的距离和路径
int ans = d1[E]; // 初始解解为直达距离
vector<int> path = paths1[E]; // 初始解的station序列
int midpoint = -1; // 不坐商业线
scanf("%d", &K);
for(int i = 0; i < K; i++) {
scanf("%d%d%d", &X, &Y, &Z); X--; Y--;
for(int j = 0; j < 2; j++) { // j=0代表商业线坐X->Y,j=1代表Y->X
if(d1[X] + d2[Y] + Z < ans) {
ans = d1[X] + d2[Y] + Z;
path = paths1[X];
for(int j = paths2[Y].size()-1; j >= 0; j--) // 从Y到T的距离要反过来
path.push_back(paths2[Y][j]);
midpoint = X;
}
swap(X, Y);
}
}
if(kase != 0) printf("\n");
kase++;
for(int i = 0; i < path.size()-1; i++) printf("%d ", path[i]+1);
printf("%d\n", E+1);//格式有的严格....oj就这样,加油吧
if(midpoint == -1) printf("Ticket Not Used\n"); else printf("%d\n", midpoint+1);
printf("%d\n", ans);
}
return 0;
}
求单源最短路树
把p看出父指针,则所有点形成了一棵树(有n-1条边,起点的p值等于它自己,其他点u对应一条边p
下次再写...留坑待补
统计路径
枚举两点间所有的最短路:
做法: 先求出d, 然后从起点开始出发,但只沿着d[j] = d[i] + w(i,j)
统计最短路的条数:
(f[i]表示从i到目标节点的最短路条数
做法: f[i] = sum(f[j] | d[j] = d[i] + w(i,j) ) 边界条件: f[e终点]为1
温馨提示: 在最短路中,因为遍历的需要,常常从终点逆推,这种情况下就要注意图的单双向了, 双向好说,可以直接按正常的来;单向的话...需要反向
补:若是需要打印路径,建议在写的时候用一个vector;
题意:Jimmy打算每天沿着一条不同的路走,而且,他只能沿着满足如下条件的道路(A,B):存在一条从B出发回家的路径,比所有从A出发回家的路径都短,你的任务是计算有多少条不同的路径
注意,这里出发点为1--,目的点为2--。
/*熟悉高中恒成立问题的人都知道,题意如下:
他只想沿着(A,B) 且 d[B] < d[A] 的路径走
这样,我们在算出d之后创建一个新图: 仅当 d[B] < d[A]时, 加入(A,B)
这是个DAG, 用DP做*/
//题目相关
int n,m;
Dijkstra solve;
int x,y,z;
int f[MAXN];
int dp(int x) {
if(x == 1) return 1;//到家了
int& ans = f[x];//记忆化搜索中常用的,方便
if(ans >= 0) return ans;
int y;
ans = 0;
for(int i = 0; i < solve.G[x].size() ; i++) {
y = solve.edges[solve.G[x][i]].y;//双向的就是简单写
if(solve.d[y] < solve.d[x]) ans += dp(y);
}
return ans;
}
int main() {
while(scanf("%d%d",&n,&m) == 2) {
solve.init(n);
for(int i = 0; i < m; i++) {
scanf("%d%d%d",&x,&y,&z);
x--,y--;
solve.add_edge(x,y,z);
solve.add_edge(y,x,z);
}
solve.dijkstra(1);//家
memset(f, -1, sizeof(f));
//特别注意: 记忆化搜索中的特殊判定!!:要分清"取不到 " 和 “值为0”
//貌似这题没有等于0的,可以设为0 ,并将 ">= 0" 改下
printf("%d\n", dp(0));
}
return 0;
}
dij的后记(补):
- 存在负边但无负环的最短路, dij不一定能求出解
- 无负边的, 多次dij可以求出任意两点之间的路径(如上
关于用链式前向星实现的最短路打印
方法很简单,在Edge里加个x , cnt, 分别为边的起点与边的编号, 因此,应该在初始化时,将edge的编号加上,之后的遍历方法就差不多了
dijkstra的stl实现(最近觉得挺方便的的更多相关文章
- 【SPFA与Dijkstra的对比】CDOJ 1961 咸鱼睡觉觉【差分约束-负权最短路径SPFA】
差分约束系统,求最小值,跑最长路. 转自:https://www.cnblogs.com/ehanla/p/9134012.html 题解:设sum[x]为前x个咕咕中至少需要赶走的咕咕数,则sum[ ...
- HDU 1102 Constructing Roads (最小生成树)
最小生成树模板(嗯……在kuangbin模板里面抄的……) 最小生成树(prim) /** Prim求MST * 耗费矩阵cost[][],标号从0开始,0~n-1 * 返回最小生成树的权值,返回-1 ...
- P4009 汽车加油行驶问题
P4009 汽车加油行驶问题 最短路 清一色的spfa....送上一个堆优化Dijkstra吧(貌似代码还挺短) 顺便说一句,堆优化Dj跑分层图灰常好写 #include<iostream> ...
- ZJOI2017游记
$Day$ $-1$ 听说可以去$ZJOI2017$打酱油,终于可以出去走走辣$QAQ$... 上次出去打比赛似乎是$PKUSC$?? 好吧,至少可以一览国家预备队爷们的风采... 准备把膝盖留在浙江 ...
- hihoCoder#1086 Browser Caching
原题地址 list+map可以轻松搞定,如果不借助STL实现起来还是挺麻烦的 代码: #include <iostream> #include <string> #includ ...
- POJ1833 排列 调用全排列函数 用copy函数节省时间 即使用了ios同步代码scanf还是比较快
排列 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21268 Accepted: 8049 Description 题 ...
- [考试反思]1031csp-s模拟测试96:常态
按照smily的说法这一场的大众分暴力分是不是265啊QwQ那我可真是个大垃圾 总算还是回归了常态. T3文件名写错,把“city.in”写成“city,in” 还好,只丢了20分. T2乱打$O(n ...
- 基于STL优先队列和邻接表的dijkstra算法
首先说下STL优先队列的局限性,那就是只提供入队.出队.取得队首元素的值的功能,而dijkstra算法的堆优化需要能够随机访问队列中某个节点(来更新源点节点的最短距离). 看似可以用vector配合m ...
- 【bzoj1922】[Sdoi2010]大陆争霸 - STL - dijkstra
信仰斯普林·布拉泽的克里斯国教徒. 幻想历 8012年 3月2日,位于杰森国东部小镇神谕镇的克里斯国教徒发动 起义. 幻想历 8012年 3月7日,神谕镇的起义被杰森国大军以残酷手段镇压. 幻想历 8 ...
随机推荐
- ubuntu下查看如何配置pycharm
ubuntu中PyCharm的安装与卸载 https://blog.csdn.net/weixin_31484477/article/details/81133590 pycharm ModuleNo ...
- CDR如何使用钢笔工具进行完美抠图?【6·18特惠倒计时!】
不要以为抠图只能在图像处理软件中实现,矢量图形绘制软件CorelDRAW一样可以,而且方法很多,文章介绍使用CDR钢笔工具抠图的方法. 提示说明: 首先说明一下,CDR中的钢笔工具和其他平面设计软件中 ...
- VMware或者KVM克隆的虚拟机网卡无法启动
在VMware里克隆出来的CentOS Linux.. ifconfig...没有看到eth0..然后重启网卡又报下面错误. 故障现象: service network restartShutting ...
- 记录--git命令行上传项目到github仓库
由于公司一直使用的是的SVN,基本上都是内网,原来的git命令都快忘记了,当然也是自己太懒,平时都是直接拖到github上.今天打开idea后突然看到了原来自己写好的一个项目,就想将它上传到githu ...
- MVC Ajax调用Action时-OnActionExecuting RedirectResult 无法跳转的处理办法
public class BaseController : Controller { protected override void OnActionExecuting(ActionExecuting ...
- APIshop精选接口助力双十一电商业务
距离2018年双11的购物盛典已经不到一个月了,各大电商之间的战役已经悄然打响,今年的双11仍会是一场电商鏖战,想必又会打破2017年双11近2540亿的全网成交总额记录. 据统计,去年双11全天共产 ...
- Eclipse安装和使用TFS
第一步下载Tfs插件 去微软官网下载https://www.microsoft.com/en-us/download/details.aspx?id=4240 点击 选择下载 随便放置到一个本地或者服 ...
- 1 Excel
#region 设置页边距 //sheet.SetMargin(MarginType.LeftMargin, (double)0.6 / 3); //sheet.SetMargin(MarginTyp ...
- HDU-4055 Number String 动态规划 巧妙的转移
题目链接:https://cn.vjudge.net/problem/HDU-4055 题意 给一个序列相邻元素各个上升下降情况('I'上升'D'下降'?'随便),问有几种满足的排列. 例:ID 答: ...
- 【codeforces 767D】Cartons of milk
[题目链接]:http://codeforces.com/problemset/problem/767/D [题意] 每个牛奶都有最晚可以喝的时间; 每天喝K瓶牛奶; 你有n瓶牛奶->已知每个牛 ...