最短路..(有全源以及有负权边的)
有人破防了,我不说是谁,但真的裂开,两个板子都爆炸了真的是nmd个b我受不了,对于这些板子的失误真的让人难以接受,垃圾,还有线段树,服了还得补这一篇博客来补救,我是垃圾,被别人爆杀了。
dj的板子:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,len=0,last[2000000],dis[2000000];
struct pp
{int x,y,c,next;
};pp p[2000000];
struct node
{int dis,now;friend bool operator <(const node &x,const node &y){return x.dis>y.dis;};
};priority_queue<node> q;
bool v[2000000];
void ins(int x,int y,int c)
{int now=++len;p[now]={x,y,c,last[x]};last[x]=now;return ;
}
void dj(int ST)
{memset(v,true,sizeof(v));memset(dis,63,sizeof(dis));node e;e.now=ST;e.dis=0;q.push(e);dis[ST]=0;while(q.size()!=0){node x=q.top();q.pop();if(v[x.now]==false) continue ;v[x.now]=false;for(int i=last[x.now];i!=-1;i=p[i].next){int y=p[i].y;if(dis[y]>dis[x.now]+p[i].c){dis[y]=dis[x.now]+p[i].c;e.now=y;e.dis=dis[y];q.push(e); }}} return ;
}
signed main()
{memset(last,-1,sizeof(last));int ST;scanf("%lld%lld%lld",&n,&m,&ST);for(int i=1;i<=m;i++){int x,y,c;scanf("%lld%lld%lld",&x,&y,&c);ins(x,y,c); }dj(ST);for(int i=1;i<=n;i++) {if(dis[i]!=dis[0]) printf("%lld ",dis[i]);
// else printf("2147483647 ");}return 0;
}
注意啦,dj不能处理负权边:https://blog.csdn.net/baidu_31818237/article/details/50611592可以看看,我自己的理解是这个若是出现负权,那么就会违背贪心的本质。也就是走较长路更优。
写一个spfa的真的服了。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int len=0,last[1000001];
int n,m,dis[100001];
int q[100001];
struct pp
{int x,y,c,next;
};pp p[1000001];
bool v[1000001];
void ins(int x,int y,int c)
{int now=++len;p[now]={x,y,c,last[x]};last[x]=now; return ;
}
void spfa(int ST)
{memset(dis,63,sizeof(dis));memset(v,true,sizeof(v));int st=1,ed=2;q[st]=ST;dis[ST]=0,v[ST]=false;while(st!=ed){int x=q[st];st++;v[x]=true;for(int i=last[x];i!=-1;i=p[i].next){int y=p[i].y;if(dis[y]>dis[x]+p[i].c){dis[y]=dis[x]+p[i].c;if(v[y]==true) v[y]=false,q[ed++]=y;}}}return ;
}
signed main()
{memset(last,-1,sizeof(last));int ST;scanf("%lld%lld%lld",&n,&m,&ST);for(int i=1;i<=m;i++){int x,y,c;scanf("%lld%lld%lld",&x,&y,&c);ins(x,y,c);}spfa(ST);for(int i=1;i<=n;i++){if(dis[i]!=dis[0]) printf("%d ",dis[i]);else printf("2147483647 ");}return 0;
}
学一学除spfa外处理负环的方法?也就是dj的处理,并且还能用来处理全源~ 好厉害!
考虑dj的处理,明显处理不了负环,那么考虑将所有的边权变为非负数。一种容易想到的方案是所有的边加上一个值,那么可以给出证明:若是每一条边都加上的一个数,那么一条路径其对结果贡献会加上其路径上边的数量 * 加的那个数,那这样明显是不行的。
那么我们先说做法:先建一个0号点,然后我们从0点跑一遍最短路,记为w[i],网上那些大佬没有说有负环怎么办啊害得我找了半天发现有负环直接判出去就好了呜呜呜。然后将边权转为p[i].c=p[i].c+w[x]-w[y]。那么然后直接跑n遍最短路就行。
给出证明(没有负环哈):哦对其实我们常常能听到一个词——势能,一种思想或者一个定义,取决于个人。问题在于,势能的变化量只和起点和终点的相对位置有关,而与路径无关。也其实算是一种另类的前缀和?好吧不是,比如说位移吧(高中物理一点点),其实就是一种势能的体现?那么其实这样的转化会导致距离变化为p[i].c+p[i…].c+w[1]-w[ed]。可以证明出无论如何后面的那两个值是不变的。且其和一定大于等于0。给出别人的正确性证明?
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,len=0,last[520001],w[520001],dis[520001];
struct node
{int x,dis;friend bool operator < (const node &x,const node &y){return x.dis > y.dis;};
};priority_queue<node > q2,qq;
struct pp
{int x,y,c,next;
};pp p[5200001];
int q1[5200001],num[520001];bool v[520001];
void ins(int x,int y,int c)
{int now=++len;p[now]={x,y,c,last[x]};last[x]=now;return ;
}
bool spfa(int ST)
{memset(v,true,sizeof(v));memset(num,0,sizeof(num));memset(w,63,sizeof(w));w[ST]=0;int st=1,ed=2;q1[st]=ST;v[ST]=false;while(st!=ed){int x=q1[st++];v[x]=true;for(int i=last[x];i!=-1;i=p[i].next){int y=p[i].y;if(w[y]<=w[x]+p[i].c) continue ;w[y]=w[x]+p[i].c;if(!v[y]) continue ;num[y]++;if(num[y]>=n+1) return true;v[y]=false;q1[ed++]=y; }} return false;
}
void dj(int ST)
{memset(v,true,sizeof(v));memset(dis,63,sizeof(dis));q2=qq;dis[ST]=0;node e;e.x=ST,e.dis=dis[ST];q2.push(e);while(q2.size()){node x=q2.top();q2.pop();if(!v[x.x]) continue ;v[x.x]=false ;for(int i=last[x.x];i!=-1;i=p[i].next){int y=p[i].y;if(dis[y]<=dis[x.x]+p[i].c) continue ;dis[y]=dis[x.x]+p[i].c;e.dis=dis[y],e.x=y;q2.push(e);}}return ;
}
signed main()
{memset(last,-1,sizeof(last));scanf("%lld%lld",&n,&m);for(int i=1;i<=m;i++){int x,y,c;scanf("%lld%lld%lld",&x,&y,&c);ins(x,y,c);}int ST=0;for(int i=1;i<=n;i++) ins(ST,i,0);if(spfa(ST)) {printf("-1"); return 0;}for(int i=1;i<=m;i++) p[i].c=p[i].c+w[p[i].x]-w[p[i].y];//printf("%lld\n",p[i].c);for(int i=1;i<=n;i++){dj(i);int ans=0;for(int j=1;j<=n;j++){if(dis[j]==dis[0]) ans+=(j*1e9);else ans+=(j*(dis[j]-w[i]+w[j]));}printf("%lld\n",ans);}return 0;
}
最短路..(有全源以及有负权边的)相关推荐
- 最短路之 SPFA(判环+负权)
下面有两种写法不同的时间复杂度可以根据自己的理解程度去选择 第一种: void Add(int u,double cost,int v)//邻接表存储关系 {w[top] = cost;Key[top ...
- #315 虫洞 判负权回路(bmf/spfa)
题目描述 在一个神秘岛上,有N(1 <= N <= 500)个洞口,标号1..N,它们之间有M (1 <= M <= 2500) 条通道相连. 神秘的竟然另外还有W (1 &l ...
- 从0开始详解 Johnson 全源最短路(P5905 【模板】Johnson 全源最短路)
问题引入:([模板]Johnson 全源最短路 - 洛谷) ps:(如果不想 情景带入 请直接转跳到Johnson算法详解) 目录 问题引入:([模板]Johnson 全源最短路 - 洛谷) 题目描述 ...
- Johnson全源最短路算法
我们最熟悉的全源最短路算法那肯定是Floyd. 不过Floyd的复杂度是O(n3)O(n^3)O(n3),显然难以接受. 当图比较稀疏的时候,即点数n和边数m同阶时,Johnson算法便有了用武之地. ...
- Johnson 全源最短路径算法 Java实现
Johnson 全源最短路径算法 Java实现 算法导入 算法核心 复杂度分析 时间复杂度 空间复杂度 代码实现 参考资料 End 算法导入 在之前的文章中,我们讲述了: 经典入门的Dijkstra算 ...
- 动态规划在求解全源最短路径中的应用(JAVA)--Floyd算法
参考图论算法(二)-最短路径的Dijkstra [ 单源 ] 和Floyd[ 多源 ] 解法(JAVA ) 这种算法也叫Floyd-Warshell算法,虽然和Warshell算法名字相近,算法思想也 ...
- 单源最短路和多源最短路
目录 一. 迪杰斯特拉(Dijkstra,单源最短路) 特点: 二. 弗洛伊德(Floyd,多源最短路) 算法过程 特点 一. 迪杰斯特拉(Dijkstra,单源最短路) Dijkstra (迪杰斯特 ...
- 全源最短路径之弗洛伊德算法(C语言)
Floyd(弗洛伊德)算法 该算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包. 时间复杂度为 O(N^3) 空 ...
- 一个交易平台源码,全源无接口
介绍: 一个交易平台源码,全源无接口 网盘下载地址: http://kekewl.net/bomkXvjjuj10 图片:
最新文章
- Unity3d多线程
- OpenCV | OpenCV彩色图像直方图算法实现
- python使用matplotlib可视化:设置坐标轴的范围、设置主次坐标轴刻度、坐标轴刻度显示样式、坐标轴刻度数颜色、小数点位数、坐标轴刻度网格线、线条类型、数据点形状标签、文本字体、颜色、大小等
- 正则表达式 右上角加号_最全正则表达式讲解实战,附源码,敲一遍学会
- BW对于SAP SD模块有哪些作用
- ssm 静态资源处理器
- 由浅到深理解ROS(5.1)- roslaunch 学习
- 罗马音平假名片假名转换器_关于五十音你所要知道的一切!文末附日网高清字帖...
- 快播王欣:区块链今天最重要的成果还只是理念布道
- 管理后台--3,修改分类
- matlab myupdatefcn,MATLAB笔记
- 计算机大学英语值最高的3项,计算机应用基础试卷
- 深入理解 Hive 分区分桶 (Inceptor)
- 国产操作系统统信UOS简单体验评测
- uni-app 获取手机类型
- svn 冲突 Error:Node remains in conflict
- IOS 调用微信扫码二维码
- python,ipython,pycharm安装
- c语言设计程序实现顺序冒泡_C语言学习 顺序程序设计
- 架设个人Web服务器实战(通过ADSL路由)