最短路径

1.单元单点最短路径问题

最简单的遍历从源节点S开始,相邻结点有很多,

1.1 深度优先与广度优先

深度优先搜索是一直往前走,只要前面有路,走到没有路为止

广度优先一源点为圆心画一个越来愈大的圆

 

dijkstra算法:不能处理负权值(效率不错)

//复习dijstra算法  不能判断负权值 
#include<iostream>
#include<cstring>
using namespace std;
const int M=0x7fffffff;
int a[1500][1500]; //存两点之间的距离
int dis[1500];//存点到目标点的距离
int book[1500];//标记已经访问的点
int m,n; //m表示点个数 
void dijstra(int m){
    int flag,u; 
    memset(book,0,sizeof(book));
//    for(int i=1;i<m;i++) cout<<book[i]<<endl;
//    cout<<"hello"<<endl;//2
    for(int i=0;i<m;i++) 
    dis[i]=a[0][i];
    book[0]=1;
    for(int i=0;i<m-1;i++){ //表示有n-1次比较 
        flag=M;
    for(int j=1;j<m;j++){//寻找没访问的剩下的离0最近的点 
        if(book[j]==0&&dis[j]<flag){
            flag=dis[j];
            u=j;
        } 
    }
    book[u]=1;
    //松弛判断 全局判断 
    for(int x=1;x<m;x++) {
        if(a[u][x]<M){
            if(dis[x]>dis[u]+dis[u]+a[u][x]) dis[x]=dis[u]+a[u][x];  //由u作为切换点 
        }
    }     
    }
//    cout<<"接过"<<endl;
    for(int i=1;i<m;i++) cout<<dis[i]<<endl;
}  
int main()
{
//    int m,n,u,v,l;    错误出现在这里
int u,v,l; 
    cin>>m>>n;
    memset(a,0x7f,sizeof(a));
    for(int i=0;i<n;i++){
        cin>>u>>v>>l;
        a[u-1][v-1]=l;
        a[i][i]=0;
    }
    dijstra(m);
} 
View Code

SPFA算法:可以处理负权值(必须掌握)

//SPFA算法  可以处理负权值 处理正权值比不上dijstra 
#include <iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAX 200001
#define INF 99999999
typedef struct XNode  //链表做好 
{
    int pow;//边的权值
    int adjvex;//
    struct XNode *next;
}Node; 

Node * head[MAX];
int visit[MAX],dis[MAX];//标记与距离 
void add(int u,int v,int w)
{
    Node *p;
    p=(Node*)malloc(sizeof(Node)); //创建新的结点 
    p->pow=w; //权值 
    p->adjvex=v;//
    p->next=head[u]; //下一个点 
    head[u]=p; //出发点 
}
void SPFA(int n)
{
    int u,v,w;
    queue<int>Q;//这个算法关键使用队列来处理问题
    Node *p;
    for(int i=1;i<=n;i++)//初始化
    {
        visit[i]=0; //未被访问 
        dis[i]=INF;//距离初始最远 
    }
    Q.push(1);//头结点进队
    dis[1]=0;
    visit[1]=1;
    while(!Q.empty())//直到队列为空才结束循环
    {
        u=Q.front();//头结点
        Q.pop();//进队
        for(p=head[u];p!=NULL;p=p->next)
        {
            v=p->adjvex;
            w=p->pow;
            if(dis[u]+w<dis[v])
            {
                dis[v]=dis[u]+w;
                if(!visit[v])
                {
                    visit[v]=1;
                    Q.push(v);//出队
                }
            }
        }
    }
}
int main()
{
    int n,m,u,v,w;
    while(cin>>n>>m){
    memset(head,NULL,sizeof(head));//初始化链表 
    for(int i=1;i<=m;i++)
    {
    scanf("%d%d%d",&u,&v,&w);
    add(u,v,w);
    }
    SPFA(n);
    for(int i=2;i<=n;i++)
        cout<<dis[i]<<endl;
    }
    return 0;
}
View Code

 bell_man算法:理解就行

 2.多点最短路径问题

posted @ 2019-02-13 15:46  Hello_World2020  阅读(174)  评论(0编辑  收藏  举报