zoukankan      html  css  js  c++  java
  • hdu2544(最短路)

    hdu 2544

    Dijkstra 

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    #define  maxn  110
    #define  inf 0x3f3f3f3f3f
    struct Edge
    {
        int from,to,dist;
    }Map[11000];
    int a[maxn][maxn];
    int d[maxn];
    int visit[maxn];
    int n,m;
    void init()
    {
        memset(visit,0,sizeof(visit));
        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
          {
              a[i][j]=inf;
              if(i==j)
                a[i][j]=0;
          }
        for(int i=2;i<=maxn;i++)
            d[i]=inf;
        d[1]=0;
    }
    void Dijkstra()
    {
        for(int k=1;k<=n;k++)  //循环n次是因为每次都找到了一个距离源点最近的点,n次就找完了所有距离源点最近的点,可以看成有两个集合,一个集合代表已找出距离源点最近的点,一个是还未找出的点
        {
          int m=inf;
          int x;
          for(int i=1;i<=n;i++)  //暴力枚举未找出最小距离的点中的与源点相连的最小距离的点
          {
            if(!visit[i] && d[i]<m)
             {
                     x=i;
                    m=d[i];
             }
          }
          visit[x]=1;
          for(int i=1;i<=n;i++)  //更新
          {
              if(a[x][i]!=inf)
              d[i]=min(d[i],d[x]+a[x][i]);
          }
        }
       // for(int i=1;i<=n;i++)
       // printf("%d ",d[i]);
      //  cout<<endl;
         printf("%d
    ",d[n]);
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m) && n!=0 && m!=0)
        {
            init();
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d",&Map[i].from,&Map[i].to,&Map[i].dist);
                a[Map[i].from][Map[i].to]=Map[i].dist;
                a[Map[i].to][Map[i].from]=Map[i].dist;
            }
    
            Dijkstra();
    
        }
       // system("pause");
        return 0;
    }
    

    Dijkstra(优先队列优化,优化的是每次选取距离源点最近的点,裸的是暴力枚举) 

        Dijkstra使用优先队列,虽然同一个点可以多次入队(因为每个节点都可以被其他节点多次刷新),但是done数组保证了一个点真正pop出来刷新其他点的时候只有一次

       当第一次出队去更新别人的时候,done[i]=true,之后判断一下就可以了。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    using namespace std;
    #define  maxn  110
    #define  inf 0x3f3f3f3f3f3f
    struct Edge
    {
        int from,to,dist;
    };
    vector <int>  G[maxn*4];  //存图的编号
    vector <Edge> edges;
    
    int d[maxn];
    int visit[maxn]; //标记是否在队列里
    int n,m;
    
    priority_queue < int >  q;
    
    void init()
    {
        for(int i=0;i<=n;i++)
            G[i].clear();
        edges.clear();
        memset(visit,0,sizeof(visit));
        for(int i=1;i<=n;i++)
            d[i]=inf;
        d[1]=0;
    }
    void AddEdge(int from,int to,int dist)
    {
        Edge edge;
        edge.from=from; edge.to=to; edge.dist=dist;
        edges.push_back(edge);
        int SIZE=edges.size();
        G[from].push_back(SIZE-1);
    }
    void Dijkstra()  //由于每次出队的都是最小值,保证每个节点只进队一次。
    {
         q.push(1);
         while(!q.empty())
         {
             int x=q.top();
             q.pop();
             for(int i=0;i<G[x].size();i++)
             {
                 Edge e=edges[G[x][i]];
                 if(d[e.to]>d[e.from]+e.dist)
                 {
                    d[e.to]=d[e.from]+e.dist;
                    q.push(e.to);
                 }
             }
         }
       // for(int i=1;i<=n;i++)
        // printf("%d ",d[i]);
        // cout<<endl;
        printf("%d
    ",d[n]);
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m) && n!=0 && m!=0)
        {
            init();
            for(int i=1;i<=m;i++)
            {
               int from,to,dist;
               scanf("%d%d%d",&from,&to,&dist);
               AddEdge(from,to,dist);
              AddEdge(to,from,dist);
            }
             Dijkstra();
        }
       // system("pause");
        return 0;
    }

      Bellman_ford(图解最短路 http://www.java3z.com/cwbwebhome/article/article1/1359.html?id=4720 ) 

      d[k][Map[i].to]=d[k-1][Map[i].from]+Map[i].dist;

    #include <iostream>
    #include <cstdio>
    #include <cstring >
    using namespace std;
    #define maxn 110
    #define inf  0x3f3f3f3f3f
    struct Edge
    {
        int from,to,dist;
    }Map[200010];
    int   d[maxn][maxn];
    int n,m;
    
    void init()
    {
         for(int k=0;k<maxn;k++)
         for(int i=1;i<maxn;i++)
            d[k][i]=inf;
        for(int k=0;k<maxn;k++)
            d[k][1]=0;
    }
    void  Bellman_foyed()
    {
          //对每条边进行n次松弛操作
        //  cout<<"fsdfsd";
            for(int k=1;k<=n;k++)
             {
                 for(int i=1;i<=m;i++)
                 {
                     if(d[k-1][Map[i].from]<inf)
                     if(d[k-1][Map[i].from]+Map[i].dist<d[k][Map[i].to])
                     {
                        d[k][Map[i].to]=d[k-1][Map[i].from]+Map[i].dist;
                     }
                 }
             }
             /*for(int k=1;k<=n;k++)
             {
                for(int i=1;i<=n;i++)
                 printf("%d  ",d[k][i]);
                 printf("
    ");
             }*/
             printf("%d
    ",d[n][n]);
    
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m) && n!=0 && m!=0)
        {
              init();
             for(int i=1;i<=m;i++)
             {
                 scanf("%d%d%d",&Map[i].from,&Map[i].to,&Map[i].dist);
                // cin>>Map[i].from>>Map[i].to>>Map[i].dist;
             }
            for(int i=m+1;i<=2*m;i++)
             {
                 Map[i].to=Map[i-m].from;
                 Map[i].from=Map[i-m].to;
                 Map[i].dist=Map[i-m].dist;
             }
             m=2*m;
             Bellman_foyed();
        }
        //getchar();
        return 0;
    }
    

     

    Bellman_ford  邻接表

     d[k][Map[i].to]=d[k-1][Map[i].from]+Map[i].dist;(省略了k这一维,可以理解成一个节点被其他节点刷新n次)

    #include <iostream>
    #include <cstdio>
    #include <cstring >
    using namespace std;
    #define maxn 110
    #define inf  0x3f3f3f3f3f
    struct Edge
    {
        int from,to,dist;
    }Map[200010];
    int   d[maxn];
    int n,m;
    
    void init()
    {
    
         for(int i=1;i<maxn;i++)
            d[i]=inf;
    
            d[1]=0;
    }
    void  Bellman_foyed()
    {
          //对每条边进行n次松弛操作
        //  cout<<"fsdfsd";
            for(int k=1;k<=n;k++)
             {
                 for(int i=1;i<=m;i++)
                 {
                     if(d[Map[i].from]<inf)
                     if(d[Map[i].from]+Map[i].dist<d[Map[i].to])
                     {
                        d[Map[i].to]=d[Map[i].from]+Map[i].dist;
                     }
                 }
             }
             /*for(int k=1;k<=n;k++)
             {
                for(int i=1;i<=n;i++)
                 printf("%d  ",d[k][i]);
                 printf("
    ");
             }*/
             printf("%d
    ",d[n]);
    
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m) && n!=0 && m!=0)
        {
              init();
             for(int i=1;i<=m;i++)
             {
                 scanf("%d%d%d",&Map[i].from,&Map[i].to,&Map[i].dist);
                // cin>>Map[i].from>>Map[i].to>>Map[i].dist;
             }
            for(int i=m+1;i<=2*m;i++)
             {
                 Map[i].to=Map[i-m].from;
                 Map[i].from=Map[i-m].to;
                 Map[i].dist=Map[i-m].dist;
             }
             m=2*m;
             Bellman_foyed();
        }
        //getchar();
        return 0;
    }
    

     Bellman_ford 邻接矩阵(一个节点被刷新n次)

     d[k][i]代表从源点经过k个点,或者说是k条边的最短距离。

      d[k][i]=min(d[k][i],d[k-1][j]+a[j][i]);

    #include <iostream>
    #include <cstdio>
    #include <cstring >
    using namespace std;
    #define maxn 110
    #define inf  0x3f3f3f3f3f
    int a[maxn][maxn];
    int d[maxn][maxn][maxn];
        int n,m;
    void init()
    {
        for(int k=0;k<maxn;k++)
        for(int i=0;i<maxn;i++)
            for(int j=0;j<maxn;j++)
           {
                a[i][j]=inf;
                d[k][i][j]=inf;
                if(i==j)
                  d[k][i][j]=0;
           }
    }
    void  Bellman_foyed()
    {
          //对每条边进行2*m次松弛操作
            for(int k=1;k<=n;k++)
             {
                 for(int i=1;i<=n;i++)
                 {
                   for(int j=1;j<=n;j++)
                   {
                       if(i!=j && a[j][i]!=inf)
                       {
                           if(d[k-1][1][j]+a[j][i]<d[k][1][i])
                          {
                            d[k][1][i]=d[k-1][1][j]+a[j][i];
                          }
                       }
                   }
                 }
             }
            /* for(int k=1;k<=n;k++)
             {
                for(int i=1;i<=n;i++)
                 printf("%d  ",d[k][1][i]);
                 printf("
    ");
             }*/
             printf("%d
    ",d[n][1][n]);
    
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m) && n!=0 && m!=0)
        {
            init();
             int from,to,dist;
              for(int i=1;i<=m;i++)
             {
                 scanf("%d%d%d",&from,&to,&dist);
                 a[from][to]=dist;
                // d[from][to]=dist;
                 a[to][from]=dist;
                // d[to][from]=dist;
             }
             Bellman_foyed();
        }
        return 0;
    }
    

      spfa

    visit数组 检查被更新的节点,保证队列里面没有相同节点,但是一个节点可以进队列多次

    用SPFA的时侯,同一个节点可能会多次入队,然后多次去刷新其他节点,这样就会导致最短路条数出现重复计算(所以才可以判断负环)

    当每个节点只进队列一次的话,退化成宽搜。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    using namespace std;
    #define  maxn  110
    #define  inf 0x3f3f3f3f3f3f
    struct Edge
    {
        int from,to,dist;
    };
    vector <int>  G[maxn*4];  //存图的编号
    vector <Edge> edges;
    
    int d[maxn];
    int visit[maxn]; //标记是否在队列里
    int n,m;
    
    queue < int >  q;
    
    void init()
    {
        for(int i=0;i<=n;i++)
            G[i].clear();
        edges.clear();
        memset(visit,0,sizeof(visit));
        for(int i=1;i<=n;i++)
            d[i]=inf;
        d[1]=0;
    }
    void AddEdge(int from,int to,int dist)
    {
        Edge edge;
        edge.from=from; edge.to=to; edge.dist=dist;
        edges.push_back(edge);
        int SIZE=edges.size();
        G[from].push_back(SIZE-1);
    }
    void spfa()
    {
       q.push(1);
       visit[1]=1;
       while(!q.empty())
       {
           //cout<<"fsdf"<<endl;
           int x=q.front();
           q.pop();
           visit[x]=0;
           for(int i=0;i<G[x].size();i++)
           {
             int next_=G[x][i];  //
             if(d[edges[next_].to]>d[edges[next_].from]+edges[next_].dist && d[edges[next_].from]<inf)
             {
                d[edges[next_].to]=d[edges[next_].from]+edges[next_].dist;
                if(visit[edges[next_].to]==0)
                {
                   visit[edges[next_].to]=1;
                   q.push(edges[next_].to);
                }
             }
           }
       }
       //for(int i=1;i<=n;i++)
       // printf("%d ",d[i]);
         //cout<<endl;
        printf("%d
    ",d[n]);
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m) && n!=0 && m!=0)
        {
            init();
            for(int i=1;i<=m;i++)
            {
               int from,to,dist;
               scanf("%d%d%d",&from,&to,&dist);
               AddEdge(from,to,dist);
              AddEdge(to,from,dist);
            }
             spfa();
        }
       // system("pause");
        return 0;
    }
    

     floyd

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define  maxn 110
    #define  inf 0x3f3f3f3f3f3f
    int n,m;
    int Map[maxn][maxn];
    int d[maxn][maxn][maxn];
    void init()
    {
        for(int i=0;i<maxn;i++)
            for(int j=0;j<maxn;j++)
            {
                Map[i][j]=inf;
                if(i==j)
                    Map[i][j]=0;
            }
    
    }
    void floyd()
    {
        for(int i=0;i<maxn;i++)
            for(int j=0;j<maxn;j++)
             d[0][i][j]=Map[i][j];
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
             for(int j=1;j<=n;j++)
             d[k][i][j]=min(d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j]);
            /* for(int i=1;i<=n;i++)
             {
                 for(int j=1;j<=n;j++)
                printf("%d ",d[i][j]);
                printf("
    ");
             }*/
             printf("%d
    ",d[n][1][n]);
    
    }
    int main()
    {
        while(scanf("%d%d",&n,&m) && n!=0 && m!=0)
        {
            init();
            int from,to,dist;
            for(int i=1;i<=m;i++)
            {
                 scanf("%d%d%d",&from,&to,&dist);
                 Map[from][to]=dist;
                 Map[to][from]=dist;
            }
    
            floyd();
        }
        return 0;
    }

      

  • 相关阅读:
    一些业内有名的网站收集
    WCF重载
    FCKEditor fckconfig.js配置,添加字体和大小 附:中文字体乱码问题解决
    查询第几条到第几条的数据的SQL语句
    SPOJ 9939 Eliminate the Conflict
    UVA 10534 Wavio Sequence
    HDU 3474 Necklace
    POJ 2823 Sliding Window
    UVA 437 The Tower of Babylon
    UVA 825 Walking on the Safe Side
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4666802.html
Copyright © 2011-2022 走看看