最短路算法

来源:互联网 发布:html嵌套php if语句 编辑:程序博客网 时间:2024/05/04 08:14

最常用的路径算法有:Bellman-Ford算法、Floyd-Warshall算法、Dijkstra算法、A*算法、Johnson算法、SPFA算法。

基本上看一遍代码就懂了哭

1.Bellman-Ford算法  

适用于DAG图(有向无环图),及负权值中。复杂度O(VxE)

/** 单源最短路bellman_ford算法,复杂度O(VE)* 可以处理负边权图。* 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路* vector<Edge>E;先E.clear()初始化,然后加入所有边* 点的编号从1开始(从0开始简单修改就可以了)*/const int INF=0x3f3f3f3f;const int MAXN=550;int dist[MAXN];struct Edge{    int u,v;    int cost;    Edge(int _u=0,int _v=0,int _cost=0):u(_u),v(_v),cost(_cost) {}};vector<Edge>E;bool bellman_ford(int start,int n)//点的编号从1开始{    for(int i=1; i<=n; i++)dist[i]=INF;    dist[start]=0;    for(int i=1; i<n; i++) //最多做n-1次    {        bool flag=false;        for(int j=0; j<E.size(); j++)        {            int u=E[j].u;            int v=E[j].v;            int cost=E[j].cost;            if(dist[v]>dist[u]+cost)            {                dist[v]=dist[u]+cost;                flag=true;            }        }        if(!flag)return true;//没有负环回路    }    for(int j=0; j<E.size(); j++)        if(dist[E[j].v]>dist[E[j].u]+E[j].cost)            return false;//有负环回路    return true;//没有负环回路}

2.Dijkstras算法

适用于权值为非负的图的单源最短路径。可用于计算正权图上的单源最短路,即从单个源点出发,到所有结点的最短路,该算法同时适用于有向图和无向图。

/** 单源最短路径,Dijkstra算法,邻接矩阵形式,复杂度为O(n^2)* 求出源beg到所有点的最短路径,传入图的顶点数,和邻接矩阵cost[][]* 返回各点的最短路径lowcost[], 路径pre[].pre[i]记录beg到i路径上的父结点,pre[beg]=-1* 可更改路径权类型,但是权值必须为非负**/const int MAXN=1010;#define typec intconst typec INF=0x3f3f3f3f;//防止后面溢出,这个不能太大bool vis[MAXN];int pre[MAXN];void Dijkstra(typec cost[][MAXN],typec lowcost[],int n,int beg){    for(int i=0; i<n; i++)    {        lowcost[i]=INF;        vis[i]=false;        pre[i]=-1;    }    lowcost[beg]=0;    for(int j=0; j<n; j++)    {        int k=-1;        int Min=INF;        for(int i=0; i<n; i++)            if(!vis[i]&&lowcost[i]<Min)            {                Min=lowcost[i];                k=i;            }        if(k==-1)break;        vis[k]=true;        for(int i=0; i<n; i++)            if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i])            {                lowcost[i]=lowcost[k]+cost[k][i];                pre[i]=k;            }    }}

/** Dijkstar 算法+堆优化* 使用优先队列优化Dijkstra算法* 复杂度O(ElogE)* 注意对vector<Edge>E[MAXN]进行初始化后加边*/const int INF=0x3f3f3f3f;const int MAXN=1000010;struct qnode{    int v;    int c;    qnode(int _v=0,int _c=0):v(_v),c(_c) {}    bool operator <(const qnode &r)const    {        return c>r.c;    }};struct Edge{    int v,cost;    Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}};vector<Edge>E[MAXN];bool vis[MAXN];int dist[MAXN];void Dijkstra(int n,int start)//点的编号从1开始{    memset(vis,false,sizeof(vis));    for(int i=1; i<=n; i++)dist[i]=INF;    priority_queue<qnode>que;    while(!que.empty())que.pop();    dist[start]=0;    que.push(qnode(start,0));    qnode tmp;    while(!que.empty())    {        tmp=que.top();        que.pop();        int u=tmp.v;        if(vis[u])continue;        vis[u]=true;        for(int i=0; i<E[u].size(); i++)        {            int v=E[tmp.v][i].v;            int cost=E[u][i].cost;            if(!vis[v]&&dist[v]>dist[u]+cost)            {                dist[v]=dist[u]+cost;                que.push(qnode(v,dist[v]));            }        }    }}void addedge(int u,int v,int w){    E[u].push_back(Edge(v,w));}

3.SPFA


** 单源最短路SPFA* 时间复杂度 0(kE)* 这个是队列实现,有时候改成栈实现会更加快,很容易修改* 这个复杂度是不定的*/const int MAXN=1010;const int INF=0x3f3f3f3f;struct Edge{    int v;    int cost;    Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}};vector<Edge>E[MAXN];void addedge(int u,int v,int w){    E[u].push_back(Edge(v,w));}bool vis[MAXN];//在队列标志int cnt[MAXN];//每个点的入队列次数int dist[MAXN];bool SPFA(int start,int n){    memset(vis,false,sizeof(vis));    for(int i=1; i<=n; i++)dist[i]=INF;    vis[start]=true;    dist[start]=0;    queue<int>que;    while(!que.empty())que.pop();    que.push(start);    memset(cnt,0,sizeof(cnt));    cnt[start]=1;    while(!que.empty())    {        int u=que.front();        que.pop();        vis[u]=false;        for(int i=0; i<E[u].size(); i++)        {            int v=E[u][i].v;            if(dist[v]>dist[u]+E[u][i].cost)            {                dist[v]=dist[u]+E[u][i].cost;                if(!vis[v])                {                    vis[v]=true;                    que.push(v);                    if(++cnt[v]>n)return false;//cnt[i]为入队列次数,用来判定是否存在负环回路                }            }        }    }    return true;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝两周岁光吃水果不吃饭怎么办 3岁宝宝光吃水果不吃饭怎么办 中学生就爱玩儿游戏不爱学习怎么办 一岁宝宝只吃水果不吃饭怎么办 孩子发烧咳嗽怎么办最有效的方法 打了百白破孩子一直发烧咳嗽怎么办 顺产侧切肛门坠胀解大便难受怎么办 2岁拉肚子拉水怎么办吃什么药 三岁宝宝三天没拉大便怎么办 3个月宝宝3天没大便怎么办 3个月宝宝4天不拉大便怎么办 17个月宝宝看见生人害怕怎么办 大人给四个月婴儿喂糖水怎么办 宝宝12个月了还一直坐着玩怎么办 七个月宝宝发烧不到38℃怎么办 一个月大的婴儿头立不起来怎么办 18个月的宝宝晚上总找妈妈怎么办 婴儿吃了妈妈生气的奶上火怎么办 3个月的宝宝认人怎么办 十天大的婴儿大便是泡沫该怎么办 婴儿3天没有拉大便了怎么办 儿童两三天拉一次大便是稀便怎么办 五个月的婴儿一星期没大便怎么办 宝宝53天几天没大便了怎么办 42天宝宝4天没有大便怎么办 42天的宝宝3天没大便怎么办 6个月宝宝前额头碰青了怎么办 三个月的婴儿喝牛奶拉绿大便怎么办 已经喂了猫一个多月的高钙奶怎么办 几个月宝宝胳膊起来红豆豆怎么办 一岁半宝宝只喝牛奶不吃饭怎么办 儿子一生下来脖子上有淋巴结怎么办 满月宝宝睡觉不踏实易惊醒怎么办 两个月宝宝从婴儿车上掉下来怎么办 兔子不吃兔粮不喝水不拉粑粑怎么办 兔子吃了带水的菜叶怎么办 七个月的宝宝晚上睡觉总醒怎么办 紫薯和番茄一起吃了怎么办 1当半宝宝喝温开水后打隔怎么办 婴儿屁股拉便便肛门有点烂了怎么办 婴儿便便之后肛门就红怎么办