hdu 2544 最短路

hdu 2544 最短路  

2011-07-16 08:56:10|  分类: 图论|字号 订阅

这题道是有关    最短路裸题。一开始在求最短集合里面到外集合的最短路径的时候,把vis[i]写成了vis[j]。让程序一直都出错。
思路:( Dijkstra 算法)
从单源点st开始,在外集合当中寻找离最短路集合最近的在外集合当中的点 i 。逐层往外延伸,延伸的同时需要不断更新从st到外集合 j 点距离dis[j].如果从最短集合里面经过 i 点再到 j 点的距离比原来的dis[j]还要近的话,那就更新dis[ j ]。该算法的时间复杂度是(n^2),空间复杂度为(n^2)
代码:
#include<iostream>
using namespace std;
#define MDIS    1000000
int dis[110],map[110][110],vis[110];//map[i][j]表示从i点到j点的距离。若两点间无通路,则距离为无穷大,vis[i]则表示i点是否已经在最短集合当中,dis[i]表示i 点到源点的最短距离

int main()
{
    int n,m,min,i,j,v,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
    {
                                                  for(i=1;i<=n;i++)
                                                          for(j=1;j<=n;j++) map[i][j]=MDIS;
    for(i=0;i!=m;i++)
    {
            scanf("%d%d%d",&a,&b,&c);
            map[a][b]=c;
            map[b][a]=c;
    }
    memset(vis,0,sizeof(vis));
    vis[1]=1;
    for(i=1;i<=n;i++)  dis[i]=map[1][i];
    for(i=1;i<n;i++)
    {
                     //cout<<"good"<<endl;
            min=MDIS;
            for(j=1;j<=n;j++)
            {
                              //cout<<"good"<<endl;
                    if(!vis[j]&&min>dis[j])//这里应该是j这个点没有放入最短集合当中 
                    {
                                           min=dis[j];
                                           v=j;
                    }
            }
            vis[v]=1;
            for(j=1;j<=n;j++)
            {
                             //cout<<"good"<<endl;
                    if(!vis[j]&&dis[v]+map[v][j]<dis[j]) dis[j]=dis[v]+map[v][j];
            }
    }
    printf("%d\n",dis[n]);
    }
    return 0;
}
 
思路:(floyd-warshall 算法)如果用这个算法做这题的话,那样这就和传递闭包的问题一样。通过找出 i 点与 j 点间的最短距离来得出出发点与目标点的最短距离。而在这个过程中,需要列举 i 点及 j 点间的所有可能的中间点。当找到一个中间点 k 使,map[i][j]  > map[i][k]+map[k][j]。这时更新map[i] [j]。同时,在初使化的时候应当将所的点间的距离初使化为无穷大。这个算法的时间复杂度是(n^3)比上面的算法慢。不过这个算法写得来短得多。
代码:
#include<iostream>
#define MDIS 1000000
using namespace std;
int map[110][110];

int main()
{
    int a,b,c,m,n,i,j,k;
    while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
    {
                                                  for(i=1;i<=n;i++)
                                                                   for(j=1;j<=n;j++) map[i][j]=MDIS;
                                                  for(i=0;i!=m;i++)
                                                  {
                                                                   scanf("%d%d%d",&a,&b,&c);
                                                                   map[a][b]=c;//这个要这样将a和b互换而且同时赋矛c是因为题目给的那路径并没有一个规定的顺序例如:map[3][1]=map[3][2]+map[2][1]不成立,,假如换回来map[1][3][=map[1][2]+map[2][3];这样也不可以保证正确性。
                                                                   map[b][a]=c;
                                                  }
    for(k=1;k<=n;k++)
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    {
                     if(map[i][j]>map[i][k]+map[k][j])
                                                      map[i][j]=map[i][k]+map[k][j];
    }
    printf("%d\n",map[1][n]);
    }
return 0;
思路:(BF算法)这个算法确实不怎样,效率比较低,不过自己对这个算法的实现也不太明白。不清楚为什么一定要用结构体。这里的核心代码是一个二重循环,外疏层循环是一个n-1次(n为图中点的个数)。这里面为什么最多是n-1次呢,我想是因为当要得到一个最短路径,途经的边最多为n-1个。因为有环的情况都可以排除。通过不断地松驰达到求最短路径。这个算法的效率为(VE)。
#include<iostream>
using namespace std;
#define MDIS 100000
struct path
{
       int s,e,c;
}pa[10005];
int d[110];
int main()
{
    int n,m,i,j,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
    {
               for(i=0;i!=m;i++)
               {
                                scanf("%d%d%d",&a,&b,&c);
                                pa[i].s=a,pa[i].e=b,pa[i].c=c;
               }
               for(i=0;i!=110;i++)  d[i]=MDIS;
               d[1]=0;
               for(i=0;i<n-1;i++)
               {
                                 for(j=0;j<m;j++)
                                 {
                                                  if(d[pa[j].s]+pa[j].c<d[pa[j].e])   d[pa[j].e]=d[pa[j].s]+pa[j].c;
                                                  if(d[pa[j].e]+pa[j].c<d[pa[j].s])   d[pa[j].s]=d[pa[j].e]+pa[j].c;
                                 }
               }
               printf("%d\n",d[n]);
    }
    return 0;
    }
(二维数组实现):效率比用结构体实现更慢。而且感觉像是在用floyd算法。
代码:
#include<iostream>
#define MDIS 1000000
using namespace std;
int map[110][110],bst[110];
int main()
{
    int i,j,m,n,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
    {
                                                  for(i=0;i!=110;i++)
                                                  {
                                                                     bst[i]=MDIS;
                                                                     for(j=0;j!=110;j++) map[i][j]=MDIS;
                                                  }
                                                  bst[1]=0;
                                                  //bst[0]=0;
                                                  for(i=0;i!=m;i++)
                                                  {
                                                                   scanf("%d%d%d",&a,&b,&c);
                                                                   map[a][b]=c;
                                                                   map[b][a]=c;
                                                  }
   // cout<<map[1][2]<<endl;
    for(i=0;i<n-1;i++)
    {
                      for(j=1;j<=n;j++)
                      {
                                       for(int k=1;k<=n;k++)
                                       {
                                               if(map[j][k]!=MDIS)
                                               {                
                                               if(bst[j]>bst[k]+map[k][j])
                                                                          bst[j]=bst[k]+map[k][j];
                                               if(bst[k]>bst[j]+map[k][j])
                                                                          bst[k]=bst[j]+map[k][j];
                                               }
                                       }
                      }
    }
    printf("%d\n",bst[n]);
    }
return 0;
}
SPFA算法:
代码:
#include<iostream>
#define MDIS 1000000
using namespace std;
int bst[110],map[110][110],queue[100*110],m,n;
bool vis[110];
void SPFA(void)
{
     int u;
     int front=0,rear=1;
     queue[0]=1;
     bst[1]=0;
     vis[1]=true;
     while(front<rear)
     {
                      u=queue[front++];
                      vis[u]=false;
                      for(int i=1;i<=n;i++)
                      {
                              if(bst[i]>bst[u]+map[u][i])
                              {
                                                         bst[i]=bst[u]+map[u][i];
                                                         if(!vis[i])
                                                         {
                                                                    queue[rear++]=i;
                                                                    vis[i]=true;
                                                         }
                              }
                      }
     }
}

int main()
{
    int a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
    {
                                                  for(int i=0;i<=n;i++)
                                                  {
                                                          bst[i]=MDIS;
                                                          vis[i]=false;
                                                          for(int j=0;j<=n;j++)
                                                          {
                                                                  map[i][j]=MDIS;
                                                          }
                                                  }
                                                 // for(int i=1;i<=n;i++) bst[i]=map[0][i];
    for(int i=0;i!=m;i++)
    {
            scanf("%d%d%d",&a,&b,&c);
            map[a][b]=c;
            map[b][a]=c;
    } 
    SPFA();
    printf("%d\n",bst[n]);
    }
    return 0;
}

dij + heap优化:这里要类比无优化的dij算法。heap的作用是让我们在查找最短的dis[ i ]的时候,效率提升为logn.不过因为,这个题的数据太小(只有100),所以不能很好地体现heap优化的效用
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define N 110
#define inf 99999999
using namespace std;
int map[N][N],dis[N];
bool vis[N];
struct node
{
       int u,dist;
       bool operator<(const node &a) const
       {
            return dist > a.dist;
       }
};
node temp;
priority_queue<node> Q;
vector<int> g[N];
int n;
void dij ()
{
     temp.u = 1;
     temp.dist = 0;
     while (!Q.empty()) Q.pop();
     Q.push(temp);
     for (int i = 1;i <= n;i ++)
     {
         dis[i] = inf;
         vis[i] = false;
     }
     dis[1] = 0;
     while (!Q.empty())
     {
           int u = Q.top().u;
           Q.pop();
           if (vis[u]) continue;
           vis[u] = true;
           int len = g[u].size();
           if (u == n) break;
           for (int i = 0;i != len;i ++)
           {
               int j = g[u][i];
               if ( !vis[j] && dis[j] > dis[u] + map[u][j])
               {
                  dis[j] = dis[u] + map[u][j];
                  temp.u = j;
                  temp.dist = dis[j];
                  Q.push(temp);
               }
           }
     }
     printf ("%d\n",dis[n]);
}

int main ()
{
    int m,x,y,c;
    while (~scanf("%d%d",&n,&m))
    {
          if (n ==0 && m == 0) break;
          for (int i = 1;i <= n;i ++)
              for (int j = 1;j <= n;j ++) map[i][j] = inf;
          for (int i = 1;i <= n;i ++) 
          {
              g[i].clear();
              map[i][i] = 0;
          }
          for (int i = 0;i != m;i ++)
          {
              scanf("%d%d%d",&x,&y,&c);
              if (map[x][y] < inf)
              {
                 map[x][y] = map[y][x] = min(map[x][y],c);
              }
              else
              {
                  map[x][y] = map[y][x] = c;
                  g[x].push_back(y);
                  g[y].push_back(x);
              }
          }
          dij();
    }
return 0;
}

你可能感兴趣的:(c,算法,优化,struct,ini,Path)