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 ...
随机推荐
- models中,对于(Small)IntegerField类型字段的choices参数在前端的展示
# models.py class UserInfo(models.Model): gender_choices = ( (1, "男"), (2, "女"), ...
- BUAA_OO_博客作业二
1.作业设计策略 1.1第一次作业 第一次作业指导书要求是一个单部多线程傻瓜调度(FAFS)电梯的模拟,由于为了可扩展性和模块化设计,第一次作业我采用了三线程,即输入处理线程,调度器线程,电梯线程 ...
- 一个电商项目的Web服务化改造2:现有项目的5个问题
最近一直在做一个电商项目,需要把原有单系统架构的项目,改造成基于服务的架构,SOA. 有点挑战,做完了,会有很大进步, 1.现有项目的问题 1.1代码风格不统一 不同的 ...
- css进阶----盒子模型,Reset CSS,css浮动,css定位,z-index属性
盒子模型 把页面上的每一个元素当成一个盒子 由内容,内边距,边框,外边距组成 盒子模型举例 <!DOCTYPE html> <html lang="en"> ...
- Java基础学习总结(72)——提升 java 代码的运行效率
前言 代码 优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没 ...
- Restful传递数组参数的两种方式
第一种,直接传递数组 js直接传递数组 var data = ["123","456"];that.loadDictionarys(data).subscrib ...
- E - Period
For each prefix of a given string S with N characters (each character has an ASCII code between 97 a ...
- HDU 5293
树上DP题. 其实有点类似于01的问题.方程很容易想到.首先,因为一条链的节点其实都是在树上的,所以很容易想到应该先求一个LCA.然后,当某节点不是链的LCA时,它的转移就是: dp[i]=sum[i ...
- mysql无密码重启
mysql无密码重启 /etc/init.d/mysql stopnohup /usr/bin/mysqld_safe --user=mysql --skip-grant-tables &
- (IT/互联网行业)你给自己当前的职位拼几分?(评分标准,个人看法,勿喷~)
常常有身边的关系好的朋友或网友.问如今我该不该跳槽的问题. 我一般给他们的答复你能给当前的工作拼几分. 下面是我自己总结的一个评分标准.如有不当之处,勿喷~ --------------------- ...