1. 程式人生 > >最短路模板合集~(Dij+Floyd+Spfa)

最短路模板合集~(Dij+Floyd+Spfa)

自己整理的最短路模板,,對於最短路問題主要就是難在構圖方面~~

//Dijstra   O(n^2)
//Dijkstra對於有負邊權的最短路徑不支援

void Dijstra()
{
    int i,j;
    for(i=0; i<n; ++i)
    {
        dis[i]=INF;
        vis[i]=0;
    }
    dis[1]=0;
    int v;
    for(i=1; i<=n; ++i)
    {
        min=INF;
        for(j=1; j<=n; ++j)
        {
            if(!vis[j]&&d[j]<min) //每次找點的過程,首先這個點沒有被發現,然後找一個最小點
            {
                min=d[j];
                v=j;
            }
        }
        vis[v]=1;

        for(j=1; j<=n; ++j) //加進最小點後,再修改從源點沒有被發現的點的最短路徑
        {
            if(!vis[j]&&dis[v]+mp[v][j]<dis[j])
                dis[j]=dis[v]+mp[v][j];

        }

    }
    int ans=-1;
    for(i=1; i<=n; ++i)
        if(dis[i]>ans)
            ans=dis[i];

}

int main()
{


    for(int i=0; i<n; ++i) //初始化 類似prim
        for(int j=0; j<n; ++j)
        {
            if(i!=j)
                mp[i][j]=INF;
            else
                mp[i][j]=0;
        }


    while(m--)
    {
        mp[i][j]=mp[j][i]=~~;
    }



    Dijstra();


    return 0;

}


=============================================================


//Dijstra  優先佇列+鄰接表 

//優化後複雜度為O(mlogn)


    struct point
{
    int val,id;
    point(int id,int val):id(id),val(val) {}
    bool operator <(const point &x)const
    {
        return val>x.val;
    }
};
void dijkstra(int s)
{
    memset(vis,0,sizeof(vis));
    for(int i=0; i<n; i++)
        dis[i]=INF;

    priority_queue<point> q;
    q.push(point(s,0));
    vis[s]=true;
    dis[s]=0;
    while(!q.empty())
    {
        int cur=q.top().id;
        q.pop();
        vis[cur]=true;
        for(int i=head[cur]; i!=-1; i=e[i].next)
        {
            int id=e[i].to;
            if(!vis[id] && dis[cur]+e[i].val < dis[id])
            {
                dis[id]=dis[cur]+e[i].val;
                q.push(point(id,dis[id]));
            }
        }
    }
}




=============================================================

//Floyd    O(n^3)

    void Floyd()
{
    for(int i=0; i<n; ++i)
        for(int j=0; j<n; ++j)
            mp[i][j]=mp[j][i]=~~;


    for(int i=0; i<n; ++i)
        for(int j=0; j<n; ++j)
            for(int k=0; k<n; ++k)
                if(mp[j][k]>mp[j][i]+mp[i][k])
                    mp[j][k]=mp[j][i]+mp[i][k];


}


=============================================================


//Spfa 鄰接矩陣   O(kE)E為邊數,k一般為2或3
//可以計算帶負環的迴路


    void Spfa()
{
    int i,j;
    for(int i=0; i<n; ++i)
    {
        d[i]=INF;
        vis[i]=0;
    }

    queue<int>q;
    q.push(start);
    d[start]=0;
    vis[start]=1;
    while(!q.empty())
    {
        int v=q.front();
        q.pop();
        vis[v]=0;   // 這點別忘記

        for(i=0; i<n; ++i)
        {
            if(d[i]>d[v]+mp[v][i])
            {
                d[i]=d[v]+mp[v][i];
                if(!vis[i])
                {
                    q.push(i);
                    vis[i]=1;

                }

            }

        }


    }
    int ans=-1;
    for(i=1; i<=n; ++i)
        if(d[i]>ans)
            ans=d[i];


}


int main()
{
    for(int i=0; i<n; ++i)
        for(int j=0; j<n; ++j)
        {
            if(i!=j)
                mp[i][j]=INF;
            else
                mp[i][j]=0;
        }

    while(m--)
    {
        mp[i][j]=mp[j][i]=~~;
    }


    Spfa();

    return 0;
}


=============================================================


//Spfa 鄰接表(推薦)


    struct node
{
    int v;
    int next;
    int cost;
} Edge,e[M];


//Insert
//無向圖的spfa的邊要存兩遍

void addEdge()
{
    mp[cnt].v=to;
    mp[cnt].cost=cost;
    mp[cnt].next=headlist[from];
    headlist[from]=cnt++;
    mp[cnt].v=to;
    mp[cnt].cost=cost;
    mp[cnt].next=headlist[from];
    headlist[from]=cnt++;

}

//

void Spfa()
{
    int i,j;

    for(i=0; i<n; ++i)
    {
        d[i]=INF;
        vis[i]=0;

    }

    d[start]=0;
    vis[start]=1;
    queue<int>q;
    q.push(start);
    while(!q.empty())
    {
        int v==q.front();
        q.pop();
        vis[v]=0;
        for(i=headlist[v]; i!=-1; i=mp[i].next)
        {
            int b=mp[i].v;
            if(d[b]>d[v]+mp[i].cost)
            {
                d[b]=d[v]+mp[i].cost;
                if(!vis[b])
                {
                    vis[b]=1;
                    q.push(b);

                }
            }

        }



    }
    int ans=-1;
    for(i=1; i<n; ++i)
    {
        if(d[u]>ans)
            ans=d[i];

    }


}


int main()
{

    //for(i=1; i<=n; i++)
    //   headlist[i]=-1;
    memset(head,-1,sizeof(head));

    cnt=0;
    cin>>from>>to>>cost;
    // Insert(edge1,head1,u,v,w);
    // Insert(edge2,head2,v,u,w);

}



=============================================================

    Bellman_ford
// 這種演算法比較少用,不多介紹了

//不斷進行鬆弛操作 
    void bellman_ford()
{
    int i,j,start=1;
    for(i=1; i<=n; i++)
        d[i]=INF;

    d[start]=0;

    for (i=1; i<n; i++)
    {
        //重複進行n-1次收縮
        for (j=0; j<m; j++)
        {
            //對每條邊進行收縮
            if (d[t[j].u]+t[j].w<d[t[j].v])
                d[t[j].v]=d[t[j].u]+t[j].w;
            //分別對每條邊的兩個頂點分別進行收縮
            if (d[t[j].v]+t[j].w<d[t[j].u])
                d[t[j].u]=d[t[j].v]+t[j].w;
        }
    }       //簡單說就是不斷進行鬆弛
    int ans=-1;
    for(i=2; i<=n; i++)
        if(d[i]>ans)
            ans=d[i];


}


int main()
{
    m=0;
    t[m].u=;
    t[m].v=;
    t[m].w=;
    m++;

}

~2015.9.5更新