堆优化dij
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define maxn 110 //最大顶点个数
#define INF 0xffffff //权值上限
int w[maxn][maxn]; //邻接矩阵,存储权值
int n; //顶点个数
struct node //顶点节点,保存id和到源顶点的估算距离,优先队列需要的类型
{
int id, weight; //源顶点id和估算距离
friend bool operator<(node a, node b) //因要实现最小堆,按升序排列,因而需要重载运算符,重定义优先级,以小为先
{
return a.weight > b.weight;
//priority_queue的排序比较函数和我们的观念相反. priority_queue一般就是用堆做的,默认是用less比较实现的大根堆,
//比如当先维护堆,从父结点A开始下降整理堆,它会用A的孩子B与A调用less<>对象假设名字叫cmp,会这样传参,
//if(cmp(A,B)){那么调换A,B结点值} ,less里肯定是 return A<B; 所以我们想要实现小根堆,在传参次序为(A,B)的情况下,
//只能修改比较函数cmp,如果A<B,返回false,A>B才返回真.
}
};
priority_queue<node> q; //优先队列,最小堆,实现Dijkstra的重要数据结构,用stl实现
int parent[maxn]; //每个顶点的父亲节点,可以用于还原最短路径树
bool visited[maxn]; //用于判断顶点是否已经在最短路径树中,或者说是否已找到最短路径
node d[maxn]; //源点到每个顶点估算距离,最后结果为源点到所有顶点的最短路。
void Dijkstra(int s) //Dijkstra算法,传入源顶点
{
for(int i = 1; i <= n; i++) //初始化
{
d[i].id = i;
d[i].weight = INF; //估算距离置INF
parent[i] = -1; //每个顶点都无父亲节点
visited[i] = false;
}
d[s].weight = 0; //源点到源点最短路权值为0
q.push(d[s]); //压入队列中
while(!q.empty()) //算法的核心,队列空说明完成了操作
{
node cd = q.top(); //取最小估算距离顶点
q.pop();
int u = cd.id;
if(visited[u])
continue;
visited[u] = true;
//松弛操作
for(int v = 1; v <= n; v++) //找所有与他相邻的顶点,进行松弛操作,更新估算距离,压入队列。
{
if(v != u && !visited[v] && d[v].weight > d[u].weight+w[u][v])
{
d[v].weight = d[u].weight+w[u][v];
parent[v] = u;
q.push(d[v]);
}
}
}
}
int main()
{
int m, a, b, c, st, ed;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) //邻接矩阵存储前需要初始化
for(int j = i; j <= n; j++)
w[i][j] = w[j][i] = INF;
while(m--)
{
scanf("%d%d%d", &a, &b, &c);
if(w[a][b] > c)
w[a][b]= w[b][a] = c;
}
scanf("%d%d", &st, &ed);
Dijkstra(st);
if(d[ed].weight != INF)
printf("最短路径权值为:%d\n", d[ed].weight);
else
printf("不存在从顶点%d到顶点%d的最短路径。\n", st, ed);
return 0;
}
以上为dij
https://blog.csdn.net/scutbenson/article/details/81320460
以上为spfa
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define maxn 110 //最大顶点个数
#define INF 0xffffff //权值上限
int w[maxn][maxn]; //邻接矩阵,存储权值
int n; //顶点个数
typedef pair<int,int> p1;
priority_queue< p1,vector<p1>,greater<p1> >q; //优先队列,对于pair类型数据,默认的是按照第一个域的大小来建堆,所以不用重载运算符。
int parent[maxn]; //每个顶点的父亲节点,记录路径
bool visited[maxn]; //用于判断顶点是否已经在最短路径树中,或者说是否已找到最短路径
int d[maxn]; //源点到每个顶点估算距离,最后结果为源点到所有顶点的最短路。
void Dijkstra(int s) //Dijkstra算法,传入源顶点
{
for(int i = 1; i <= n; i++) //初始化
{
d[i] = INF; //估算距离置INF
parent[i] = -1; //每个顶点都无父亲节点
visited[i] = false;
}
d[s]= 0; //源点到源点最短路权值为0
q.push(make_pair(d[s],s));
while(!q.empty()) //算法的核心,队列空说明完成了操作
{
p1 cd = q.top(); //取最小估算距离顶点
q.pop();
int u = cd.second;
if(visited[u])
continue;//很重要,因为在松弛的过程中u点肯定多次进堆,所以弹堆时候再遇见u直接弹就可以,因为最小的d[u],已经求出并且出堆。
visited[u] = true;
//松弛操作
for(int v = 1; v <= n; v++) //找所有与他相邻的顶点,进行松弛操作,更新估算距离,压入队列。
{
if(v != u && !visited[v] && d[v] > d[u]+w[u][v])
{
d[v] = d[u]+w[u][v];
parent[v] = u;//当然,如果题目让输出路径的话直接递归输出,此题没输出,只是加上让大家看一下怎么记录路径
q.push(make_pair(d[v],v));
}
}
}
}
int main()
{
int m, a, b, c, st, ed;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) //邻接矩阵存储前需要初始化
for(int j = i; j <= n; j++)
w[i][j] = w[j][i] = INF;
while(m--)
{
scanf("%d%d%d", &a, &b, &c);
if(w[a][b] > c)
w[a][b]= w[b][a] = c;
}
scanf("%d%d", &st, &ed);
Dijkstra(st);
if(d[ed] != INF)
printf("最短路径权值为:%d\n", d[ed]);
else
printf("不存在从顶点%d到顶点%d的最短路径。\n", st, ed);
return 0;
}
以上仍然为堆优化dij,但无路径
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
double dis[101][101];
int x[101],y[101];
int pre[101][101];
int n,i,j,k,m,a,b;
int pf(int x)
{
return x*x;
}
void print(int x)
{
if (pre[a][x] == 0) return; //pre[a][a]=0,说明已经递归到起点a
print(pre[a][x]);
cout << "->" << x;
}
int main()
{
cin >> n;
for (i = 1; i <= n; i++)
cin >> x[i] >> y[i];
memset(dis,0x7f,sizeof(dis)); //初始化数组
cin >> m;
memset(pre,0,sizeof(pre)); //初始化前驱数组
for (i = 1; i <= m; i++)
{
cin >> a >> b;
dis[a][b] = dis[b][a] = sqrt(pf(x[a]-x[b])+pf(y[a]-y[b]));
pre[a][b] = a; //a与b相连,自然从a到b的最短路径b的前驱是a
pre[b][a] = b;
}
cin >> a >> b;
for (k = 1; k <= n; k++) //floyed 最短路
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
if ((i != j) && (i != k) && (j != k))
if (dis[i][j] > dis[i][k]+dis[k][j])
{
dis[i][j] = dis[i][k] + dis[k][j];
pre[i][j] = pre[k][j];
//从i到j的最短路径更新为i→k→j,那么i到j最短路径j的前驱就肯定与k到j最短路径j的前驱相同。
}
cout << a;
print(b); //a是起点,b是终点
return 0;
}
弗洛伊德带路径
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
struct data
{
int q,dat;
friend bool operator<(data a, data b) //因要实现最小堆,按升序排列,因而需要重载运算符,重定义优先级,以小为先
{
return a.dat > b.dat;
//priority_queue的排序比较函数和我们的观念相反. priority_queue一般就是用堆做的,默认是用less比较实现的大根堆,
//比如当先维护堆,从父结点A开始下降整理堆,它会用A的孩子B与A调用less<>对象假设名字叫cmp,会这样传参,
//if(cmp(A,B)){那么调换A,B结点值} ,less里肯定是 return A<B; 所以我们想要实现小根堆,在传参次序为(A,B)的情况下,
//只能修改比较函数cmp,如果A<B,返回false,A>B才返回真.
}
}/*小根堆*/;
priority_queue<data> Q;
struct arr
{
int ff,tt,ww,next;
}c[5000];
data cc;//建堆用的变量
int a[5000],dis[5000],r[5000];
bool v[5000];
int n,tot = 0,p,C;
void add(int x,int y, int z)
{
c[++tot].ff = x;
c[tot].tt = y;
c[tot].ww = z;
c[tot].next = r[x];
r[x] = tot;
}
int dijsktra(int st)
{
int x,y;
cc.q = st;
cc.dat = 0;
Q.push(cc);
memset(dis,50,sizeof(dis));//初始化为较大的数8亿多
memset(v,0,sizeof(v));
dis[st] = 0;
while (! Q.empty())
{
x = Q.top().q;
y = Q.top().dat;
Q.pop();
if (! v[x])
{
v[x] = true;
for (int i = r[x]; i ; i = c[i].next)
{
cc.q = c[i].tt;
if (dis[cc.q]> y+c[i].ww)
{
dis[cc.q] = y+c[i].ww;
cc.dat = dis[cc.q];
Q.push(cc);
}
}
}
}
}
int main()
{
freopen("butter.in","r",stdin);
freopen("butter.out","w",stdout);
scanf("%d%d%d",&n,&p,&C);
int x,y,z;
for (int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
for (int i=1; i<=C; i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
int ans = 0x7fffffff;
for (int i = 1; i<=p; i++)
{
dijsktra(i);
int now = 0;
for (int j = 1; j<=n; j++)
now+=dis[a[j]];
ans = min(ans,now);
}
printf("%d\n",ans);
return 0;
}
堆优化dij
#include <bits/stdc++.h>
using namespace std;
bool a[1000][1000];
bool f[1000];
int n,e;
void iint(){
memset(a,0,sizeof(a));
memset(f,0,sizeof(f));
scanf("%d%d",&n,&e);
for(int i=1;i<=e;i++){
int x,y;
scanf("%d%d",&x,&y);
a[x][y]=true;
a[y][x]=true;
}
}
void bfs(int x){
f[x]=true;
queue<int> q;
q.push(x);
printf("%d ",x);
while(!q.empty()){
for(int i=1;i<=n;i++){
if(!f[i] && a[q.front()][i]){
q.push(i);
f[i]=1;
printf("%d ",i);
}
}
q.pop();
}
}
int main(){
iint();
bfs(1);
return 0;
}
bfs(广搜)
#include <bits/stdc++.h>
using namespace std;
bool a[110][110];
bool flag[110];
int n,e;
void init();
void dfs(int x);
int main()
{
init();
dfs(1);
return 0;
}
void init(){
scanf("%d%d",&n,&e);
memset(flag,0,sizeof(flag));
memset(a,0,sizeof(a));
int x,y;
for(int i=1;i<=e;++i){
cin>>x>>y;
a[x][y]=1;
a[y][x]=1;
}
}
void dfs(int x){
printf("%d ",x);
flag[x]=1;
for(int i=1;i<=n;++i)
if(!flag[i]&&a[x][i]==1)
dfs(i);
}
dfs(深搜)
愿你在冷铁卷刃之前,得以窥见天光

浙公网安备 33010602011771号