图论-最短路模版

Dijkstra算法-邻接矩阵形式

复杂度:N^2

/*
* Dijkstra算法,邻接矩阵形式:
* 复杂度为O(n^2),仅可处理非负权图
* cost:    任意两点边权(不相连边需赋值INF)
* n:       图中点的总数(当前点从0开始编号)
* lowcost:任意点到源点的最短路
* beg:    源点
*/
const int MAXN=1010;
#define typec int
const 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;
        }
    }
}

Dijkstra算法-邻接表形式

复杂度:Elog(E)

/*
* 优化Dijkstra,邻接表形式
* 复杂度O(ElogE),仅适合无负权图
* E[i]:  与i点相连的边的集合,初始化方式: E[i].clear()
* n:    图中点的总数,(节点编号从1开始)
* start: 源点
* dist:  各点到源点的最短路
* 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 start,int n)//点的编号从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));
}
//---------------------------------------------------------------

SPFA算法-邻接表形式

复杂度:kE

/*
* SPFA,邻接表形式
* 复杂度O(kE)(复杂度不定,改成栈有时更快),可处理负权图
* E[i]:  与i点相连的边的集合,初始化方式: E[i].clear()
* n:    图中点的总数,(节点编号从1开始)
* start: 源点
* dist:  各点到源点的最短路
* MAXN:  最大点数
*/

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;
}

Ford算法-邻接表形式

复杂度:NE

/*
* bellman_ford算法,邻接表形式
* 复杂度O(VE),可处理负权图
* E:       边集,初始化方式: E.clear()
* n:    图中点的总数,star
* start: 源点
* dist:  各点到源点的最短路
* MAXN: 最大点数
* 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路
*/

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;//没有负环回路
}

void addedge(int u,int v,int w)
{//加的是单向边,即u->v权值为w
    E.push_back(Edge(u,v,w));
}

Ford算法-求任意最短路

复杂度:N^3

//---O(n^3)的任意最短
    for(int k = 0; k < n; k++)
        for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
        if(cost[i][j]<cost[i][k]*cost[k][j])
        cost[i][j]=cost[i][k]*cost[k][j];
//--------------------------------------------
原文地址:https://www.cnblogs.com/mochenmochen/p/5156885.html