单源最短路
Floyd(纯暴力)
思想:贪心+暴力枚举;
看代码就能理解了
void Floyd()
{
//初始化dis[][]为很大的值;
//注意在输入时需要将dis[x][y],dis[y][x],都录入;
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]); //单纯的暴力枚举每一个点;
}
}
dij+优先队列优化
算法思想:
1.将与起点相连的点都遍历一次;
2·遍历的顺序为每次的最小边遍历(此处用优先队列优化,保证每一次队首都是最小边);
注意:以最小边的顺序遍历既保证了该点到其余点的路径尽量的小,逐渐更新距离;
模板题目链接
题意:即找到1点到n点的最短距离;
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e5+55;
int head[N],dis[123];
int cnt;
struct node{
int to,val,next;
}mp[N];
struct nod{ //优先队列元素,u表示节点,val表示u到起点的距离;
int u,val;
bool friend operator<(nod a, nod b)
{
return a.val>b.val;
}
};
void add(int x, int y, int val) //链式向前星建边;
{
mp[cnt].to=y;
mp[cnt].val=val;
mp[cnt].next=head[x];
head[x]=cnt++;
mp[cnt].to=x;
mp[cnt].val=val;
mp[cnt].next=head[y];
head[y]=cnt++;
}
void dij() //核心代码;
{
bool p[123];
memset(dis,inf,sizeof(dis)); //初始化,dis[];
memset(p,true,sizeof(p)); //p作为标记数组,记录节点是否已经被遍历;
dis[1]=0;
priority_queue<nod >q;
q.push(nod{1,dis[1]});
while(!q.empty()){
nod are=q.top();
q.pop();
int to,val,u;
u=are.u;
if(!p[u]) continue;
p[u]=false;
for(int i=head[u];~i;i=mp[i].next){
to=mp[i].to;
val=mp[i].val;
if(dis[to]>dis[u]+val){
dis[to]=dis[u]+val;
q.push(nod{to,dis[to]});
}
}
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&(n+m)){
int x,y,val;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;++i){
scanf("%d%d%d",&x,&y,&val);
add(x,y,val);
}
dij();
printf("%d\n",dis[n]);
}
return 0;
}
Spfa(bfs暴力搜索)
从起点出发,求两点间的距离,将其压入队列,依次更新所有的边,找到min(dis)
注意:条件dis[to]>dis[u]+val;如果相同就不压入,保证了不重复,一个点可能多次被压入队列;
题目:还是上面的例题;
Spfa算法实际就是对每一条边的遍历,有一些题可能卡数据;
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e5+55;
int head[N],dis[123];
int cnt;
struct node{
int to,val,next;
}mp[N];
void add(int x, int y, int val)
{
mp[cnt].to=y;
mp[cnt].val=val;
mp[cnt].next=head[x];
head[x]=cnt++;
mp[cnt].to=x;
mp[cnt].val=val;
mp[cnt].next=head[y];
head[y]=cnt++;
}
void Spfa() //核心代码;
{
bool p[123];
memset(dis,inf,sizeof(dis));
memset(p,false,sizeof(p));
queue<int > q;
dis[1]=0;
p[1]=true;
q.push(1);
int to,val,u;
while(!q.empty()){
u=q.front();
q.pop();
p[u]=false;
for(int i=head[u];~i;i=mp[i].next){
to=mp[i].to;
val=mp[i].val;
if(dis[to]>dis[u]+val){
dis[to]=dis[u]+val;
if(!p[to]) { //表示当u点没有再队列中时才压入队列,否则不压入;
q.push(to);
p[to]=true;
}
}
}
}
}
int main()
{
int n,m,x,y,val;
while(~scanf("%d%d",&n,&m)&&(n+m)){
memset(head,-1,sizeof(head));
for(int i=0;i<m;++i){
scanf("%d%d%d",&x,&y,&val);
add(x,y,val);
}
Spfa();
printf("%d\n",dis[n]);
}
return 0;
}