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());
}
}

例题:机场快线UVA 11374

题意: 在一张图中有两种路线,一种是经济线,一种是商业线,经济线可以随便走,但是商业线只能走一次。现在问从起点到终点的最短路是什么。

注意: 商业线也是双向的

// 题目相关(一开始写的丢了,只能去代码仓库找了...)
//作者: 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

下次再写...留坑待补

统计路径

  1. 枚举两点间所有的最短路:

    做法: 先求出d, 然后从起点开始出发,但只沿着d[j] = d[i] + w(i,j)

  2. 统计最短路的条数:

    (f[i]表示从i到目标节点的最短路条数

    做法: f[i] = sum(f[j] | d[j] = d[i] + w(i,j) ) 边界条件: f[e终点]为1

  3. 温馨提示: 在最短路中,因为遍历的需要,常常从终点逆推这种情况下就要注意图的单双向了, 双向好说,可以直接按正常的来;单向的话...需要反向

    补:若是需要打印路径,建议在写的时候用一个vector;

例题: 林中散步UVA10917

题意: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的后记(补):

  1. 存在负边但无负环的最短路, dij不一定能求出解
  2. 无负边的, 多次dij可以求出任意两点之间的路径(如上

关于用链式前向星实现的最短路打印

方法很简单,在Edge里加个x , cnt, 分别为边的起点与边的编号, 因此,应该在初始化时,将edge的编号加上,之后的遍历方法就差不多了

dijkstra的stl实现(最近觉得挺方便的的更多相关文章

  1. 【SPFA与Dijkstra的对比】CDOJ 1961 咸鱼睡觉觉【差分约束-负权最短路径SPFA】

    差分约束系统,求最小值,跑最长路. 转自:https://www.cnblogs.com/ehanla/p/9134012.html 题解:设sum[x]为前x个咕咕中至少需要赶走的咕咕数,则sum[ ...

  2. HDU 1102 Constructing Roads (最小生成树)

    最小生成树模板(嗯……在kuangbin模板里面抄的……) 最小生成树(prim) /** Prim求MST * 耗费矩阵cost[][],标号从0开始,0~n-1 * 返回最小生成树的权值,返回-1 ...

  3. P4009 汽车加油行驶问题

    P4009 汽车加油行驶问题 最短路 清一色的spfa....送上一个堆优化Dijkstra吧(貌似代码还挺短) 顺便说一句,堆优化Dj跑分层图灰常好写 #include<iostream> ...

  4. ZJOI2017游记

    $Day$ $-1$ 听说可以去$ZJOI2017$打酱油,终于可以出去走走辣$QAQ$... 上次出去打比赛似乎是$PKUSC$?? 好吧,至少可以一览国家预备队爷们的风采... 准备把膝盖留在浙江 ...

  5. hihoCoder#1086 Browser Caching

    原题地址 list+map可以轻松搞定,如果不借助STL实现起来还是挺麻烦的 代码: #include <iostream> #include <string> #includ ...

  6. POJ1833 排列 调用全排列函数 用copy函数节省时间 即使用了ios同步代码scanf还是比较快

    排列 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21268   Accepted: 8049 Description 题 ...

  7. [考试反思]1031csp-s模拟测试96:常态

    按照smily的说法这一场的大众分暴力分是不是265啊QwQ那我可真是个大垃圾 总算还是回归了常态. T3文件名写错,把“city.in”写成“city,in” 还好,只丢了20分. T2乱打$O(n ...

  8. 基于STL优先队列和邻接表的dijkstra算法

    首先说下STL优先队列的局限性,那就是只提供入队.出队.取得队首元素的值的功能,而dijkstra算法的堆优化需要能够随机访问队列中某个节点(来更新源点节点的最短距离). 看似可以用vector配合m ...

  9. 【bzoj1922】[Sdoi2010]大陆争霸 - STL - dijkstra

    信仰斯普林·布拉泽的克里斯国教徒. 幻想历 8012年 3月2日,位于杰森国东部小镇神谕镇的克里斯国教徒发动 起义. 幻想历 8012年 3月7日,神谕镇的起义被杰森国大军以残酷手段镇压. 幻想历 8 ...

随机推荐

  1. ubuntu下查看如何配置pycharm

    ubuntu中PyCharm的安装与卸载 https://blog.csdn.net/weixin_31484477/article/details/81133590 pycharm ModuleNo ...

  2. CDR如何使用钢笔工具进行完美抠图?【6·18特惠倒计时!】

    不要以为抠图只能在图像处理软件中实现,矢量图形绘制软件CorelDRAW一样可以,而且方法很多,文章介绍使用CDR钢笔工具抠图的方法. 提示说明: 首先说明一下,CDR中的钢笔工具和其他平面设计软件中 ...

  3. VMware或者KVM克隆的虚拟机网卡无法启动

    在VMware里克隆出来的CentOS Linux.. ifconfig...没有看到eth0..然后重启网卡又报下面错误. 故障现象: service network restartShutting ...

  4. 记录--git命令行上传项目到github仓库

    由于公司一直使用的是的SVN,基本上都是内网,原来的git命令都快忘记了,当然也是自己太懒,平时都是直接拖到github上.今天打开idea后突然看到了原来自己写好的一个项目,就想将它上传到githu ...

  5. MVC Ajax调用Action时-OnActionExecuting RedirectResult 无法跳转的处理办法

    public class BaseController : Controller { protected override void OnActionExecuting(ActionExecuting ...

  6. APIshop精选接口助力双十一电商业务

    距离2018年双11的购物盛典已经不到一个月了,各大电商之间的战役已经悄然打响,今年的双11仍会是一场电商鏖战,想必又会打破2017年双11近2540亿的全网成交总额记录. 据统计,去年双11全天共产 ...

  7. Eclipse安装和使用TFS

    第一步下载Tfs插件 去微软官网下载https://www.microsoft.com/en-us/download/details.aspx?id=4240 点击 选择下载 随便放置到一个本地或者服 ...

  8. 1 Excel

    #region 设置页边距 //sheet.SetMargin(MarginType.LeftMargin, (double)0.6 / 3); //sheet.SetMargin(MarginTyp ...

  9. HDU-4055 Number String 动态规划 巧妙的转移

    题目链接:https://cn.vjudge.net/problem/HDU-4055 题意 给一个序列相邻元素各个上升下降情况('I'上升'D'下降'?'随便),问有几种满足的排列. 例:ID 答: ...

  10. 【codeforces 767D】Cartons of milk

    [题目链接]:http://codeforces.com/problemset/problem/767/D [题意] 每个牛奶都有最晚可以喝的时间; 每天喝K瓶牛奶; 你有n瓶牛奶->已知每个牛 ...