最短路模板
floyed
核心思想 : 在两点间不断插入其他点看是否可以让最短距离变小
int dis[maxn][maxn];
int path[maxn][maxn];
void floyed(){
for(int i=1;i<=n;i++){//初始化
for(int j=1;j<=n;j++){
dis[i][j]=1e9;
if(i==j) dis[i][j]=0;
}
}
for(int i=1,a,b,cost;i<=m;i++){
cin>>a>>b>>cost;
dis[a][b]=dis[b][a]=cost;
path[a][b]=b;
path[b][a]=a;
}
//核心代码
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if( dis[i][j]>dis[i][k]+dis[k][j] ){
dis[i][j]=dis[i][k]+dis[k][j];
path[i][j]=path[i][k];//路径
}else if(dis[i][j]==dis[i][k]+dis[k][j]+b[k] && path[i][j]>path[i][k]){//字典序最小路径
path[i][j]=path[i][k];
}
}
}
}
//路径打印
int s,g;
for(int i=s;i!=g;i=path[i][g])
printf("%d ",i);
printf("%d",g);
}
Dijkstra
核心思想 : 不断从未选顶点集合选取到已选顶点集合的最短距离边
#define rep(x,y,z) for(int x = y; x<=z;++x)
struct cpp{
int to,cost;
}tem;
bool vis[10005];
int dis[10005];//最短距离
int path[10005];//path表示起点到i点路径的上要走的i的前一个点
priority_queue<cpp> dui;
bool operator<(const cpp&a,const cpp&b){
return a.cost>b.cost;
}
vector<cpp> g[10005];
int n,s;
void Dijkstra(){
rep(i,1,n) dis[i]=1e9;
dis[s]=0;
tem.cost=0;tem.to=s;
dui.push(tem);
int u;
while(!dui.empty()){
u=dui.top().to;
dui.pop();
if(vis[u]) continue;
vis[u]=1;
rep(i,0, (int)(g[u].size()-1) ){
if( vis[g[u][i].to]==0&&dis[g[u][i].to]>dis[u]+g[u][i].cost ){
dis[g[u][i].to]=dis[u]+g[u][i].cost;
path[g[u][i].to]=u;//更新路径
tem.to=g[u][i].to;tem.cost=dis[g[u][i].to];
dui.push(tem);
}
}
}
}
void print_path(int ed){
stack<int> mystack;
mystack.push(ed);
while(ed!=s){
ed=path[ed];
mystack.push(ed);
}
while(!mystack.empty()){
cout<<mystack.top()<<" ";
mystack.pop();
}
putchar('\n');
}
Bellman_ford
核心思想 : 俩点之间最多有n-1条边,不断进行松弛操作
#define rep(x,y,z) for(int x = y; x<=z;++x)
struct cpp{
int from,to,cost;//如果是无向图,记得存from和to交换位置再存一遍
}edge[500005];
int dis[10005];
int path[10005];//路径打印
int n,s,m;
void Bellman_ford(){
rep(i,1,n) dis[i]=1e9;
dis[s]=0;
bool flag;
rep(i,1,n-1){
flag=1;
rep(j,1,m){
if(dis[edge[j].to]>dis[edge[j].from]+edge[j].cost){
dis[edge[j].to]=dis[edge[j].from]+edge[j].cost;
path[edge[j].to]=edge[j].from;//更新路径
flag=0;
}
}
if(flag) break;
}
}
void print_path(int ed){//打印路径
stack<int> mystack;
mystack.push(ed);
while(ed!=s){
ed=path[ed];
mystack.push(ed);
}
while(!mystack.empty()){
cout<<mystack.top()<<" ";
mystack.pop();
}
putchar('\n');
}
SPFA
核心思想 : 像Bellman_ford一样不断松弛,但是优先选择被松弛的点进行松弛
#define rep(x,y,z) for(int x = y; x<=z;++x)
int n,s;
int dis[10005];
int path[10005];
bool vis[10005];
struct cpp{
int to,cost;
}tem;
vector<cpp> g[10005];
queue<int> dui;
void SPFA(){
repi(i,1,n) dis[i]=2147483647;
dis[s]=0; vis[s]=1; dui.push(s);
while(!dui.empty() ){
int x=dui.front();dui.pop();
vis[x]=0;
repi(i,0, (int) (g[x].size()-1) ){
if( dis[ g[x][i].to ]>dis[ x ] + g[x][i].cost ){
dis[ g[x][i].to ]=dis[ x ] + g[x][i].cost;
path[ g[x][i].to ]=x;//更新路径
if(vis[ g[x][i].to ]==0){
vis[ g[x][i].to ]=1;
dui.push(g[x][i].to);
}
}
}
}
}
void print_path(int ed){//打印路径
stack<int> mystack;
mystack.push(ed);
while(ed!=s){
ed=path[ed];
mystack.push(ed);
}
while(!mystack.empty()){
cout<<mystack.top()<<" ";
mystack.pop();
}
putchar('\n');
}