Several shortest path algorithm and templates

Shortest divided into single-source shortest multiple sources and sinks shortest;

A single-source shortest length according to the positive and negative sides divided into two groups (n represents a point, m represents the sides)

  (1) a positive side length

    dijkstra algorithm

    Simple Version (o (n ^ 2))

    Heap optimized version (0 (mlogn))

   When dense graph (m> = n ^ 2) time when the simple version better, with the sparse FIG better-optimized stack;

  (2) the right to have negative side

     bellman_ford Algorithm 0 (nm)

     Since SPFA bellman_ford optimization algorithm, to find the most commonly used bellman_ford short circuit limit the number of edges, as the shortest path without exceeding k edges of the note does not exist at this time that the most critical short dist [n]> 0x3f3f3f3f, because there may be, dist [t] = 0x3f3f3f3f, but there are edge t and n may loosen dist [n];

    SPFA O (m), worst-O (nm)

     Negated ring can also be used, may be used to find the shortest path is the right

2. Multi-source shortest sinks

folyd Algorithm 0 (n ^ 3) for dense FIG.

 

dijkstra algorithm simple version

#include<iostream>
#include<cstring>
using namespace std;
int g[510][510];
 int n,m;
int vis[510],dist[510];
int dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i=0;i<n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&(t==-1||dist[t]>dist[j]))
            t=j;
        }
        vis[t]=1;
        for(int j=1;j<=n;j++)
        dist[j]=min(dist[j],dist[t]+g[t][j]);
    }
    if(dist[n]==0x3f3f3f3f)return -1;
    return dist[n];
}
int main()
{
    memset(g,0x3f,sizeof g);
   cin>>n>>m;
   while(m--)
   {
       int a,b,c;
       cin>>a>>b>>c;
       g[a][b]=min(g[a][b],c);
       //g[b][a]=min(g[b][a],c);
   }
   cout<<dijkstra()<<endl;
    return 0;
}

Heap optimized version

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;
typedef pair<int,int> PII;

const int N=100010;
int h[N],e[N],ne[N],idx,w[N];
int dist[N];
bool st[N];
int n,m;

void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}
int dijktra(){
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    priority_queue<PII,vector<PII>,greater<PII>>heap;
    heap.push({0,1});
    while(heap.size()){
        auto t=heap.top();
        heap.pop();
        int ver=t.second,distance=t.first;
        if(distance>dist[ver])continue;
        for(int i=h[ver];i!=-1;i=ne[i]){
            int j=e[i];
            if(dist[j]>distance+w[i])
             {
                 dist[j]=distance+w[i];
                 heap.push({dist[j],j});
             }
        }
    }
    if(dist[n]==0x3f3f3f3f)return -1;
    return dist[n];

}

int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    cout<<dijktra()<<endl;
    return 0;
}

bellman_ford side limit for Finding

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int n,m,k;
int dist[510],bakcup[510];
struct Edge
{
    int a,b,w;
}edge[10010];
int bellmen_ford()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i=0;i<k;i++)
    {
        the memcpy (Backup, a capability, dist,the sizeof dist); // copy dist bakcup to prevent tandem array 
        for ( int J = 0 ; J <m; J ++ ) 
        { 
            int A = Edge [J] II.A, B = Edge [J] .B, W = Edge [J] .W; 
            dist [B] = min (dist [B], Backup, a capability [A] + W); // for each edge a-> b relaxation 
        } 
    } 
    IF (dist [n-]> 0x3f3f3f3f / 2 ) return - . 1 ;
     return dist [n-]; 
} 
int main () 
{ 
    CIN >> >> m >> n- K;
     for ( int I =0;i<m;i++)
    {
    int a,b,w;
    cin>>a>>b>>w;
    edge[i]={a,b,w};
    }
    int t=bellmen_ford();
    if(t==-1)printf("impossible\n");
    else
    printf("%d\n",dist[n]);
    return 0;
}

SPEA shortest seek (provided the ring is not present negative)

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int h[100010],ne[100010],e[100010],w[100010],idx;
int dist[100010],st[100010];int n,m;
void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int spea()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    queue<int>q;
    st[1]=1;q.push(1);
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=0;//t出队
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>dist[t]+w[i])
            {
                dist [J] = dist [T] + W [I];
                 IF (! ST [J]) 
                { 
                    q.push (J); 
                    ST [J] = . 1 ; 
                } 
            } 
        } 
    } 
    IF (dist [n-] == 0x3f3f3f3f ) return - . 1 ; // completely finish a certain minimum value 
    return dist [n-]; 
} 
int main () 
{ 
    CIN >> >> n- m; 
    Memset (H, - . 1 , the sizeof H);
    while(m--)
    {
        int a,b,w;cin>>a>>b>>w;
        add(a,b,w);
    }
    int t=spea();
    if(t==-1)printf("impossible\n");
    else
    printf("%d\n",t);
    return 0;
}

Loop negative determination SPFA

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int h[100010],ne[100010],e[100010],w[100010],idx;
int dist[100010],st[100010];int n,m,cnt[100010];
void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int spea()
{
    Memset (dist, NE [I])0x3F , the sizeof dist); 
    dist [ . 1 ] = 0 ; 
    Queue < int > Q;
     for ( int I = . 1 ; I <= n-; I ++ ) 
    ST [I] = . 1 , q.push (I); // negative 1 not only in the ring path starting 
    the while (q.size ()) 
    { 
        int T = q.front (); 
        q.pop (); 
        ST [T] = 0 ; // T queued 
        for ( int I = H [T]; I = -! . 1 ; I = 
        { 
            int J = E [I];
             IF (dist [J]> dist [T] + W [I]) 
            { 
                dist [J] = dist [T] + W [I]; 
                CNT [J] = CNT [T] + 1 ; // this path more than one edge 
                if (CNT [J]> = n) return  1 ; // drawer principle, after n edges, i.e., after n + 1 points, there must be two identical points 
                if (! ST [J]) 
                { 
                    q.push (J); 
                    ST [J] = . 1 ; 
                } 
            } 
        } 
    } 
    return  0 ; 
} 
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof h);
    while(m--)
    {
        int a,b,w;cin>>a>>b>>w;
        add(a,b,w);
    }
    int t=spea();
    if(t)printf("Yes\n");
    else
    printf("No");
    return 0;
}

folyd

#include<iostream>
#include<cstring>
using namespace std;
int g[510][510];
int main()
{
    memset(g,0x3f,sizeof g);
    int n,m,k;cin>>n>>m>>k;
    for(int i=1;i<=n;i++)g[i][i]=0;
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=min(c,g[a][b]);
    }
    for(int k=1;k<=n;k++)
     for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
      g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
      while(k--)
      {
          int a,b;
          cin>>a>>b;
          if(g[a][b]>0x3f3f3f3f/2)printf("impossible\n");
          else
          printf("%d\n",g[a][b]);
      }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/flyljz/p/11766146.html
Recommended