HDU1385 【输出字典序最小的最短路】

这题经过的结点比较好处理。

主要是字典序的处理。

先是floyd做法,采用记录后驱的方法。  path[i][j]=j【初始化。。。】

#include 
#include 
#include 
#include 
using namespace std;

const int maxn=5000;
const int INF=100000000;

int n;
int node[maxn];
int dist[maxn][maxn];
int path[maxn][maxn];

void floyd()
{
    for(int i=1;i<=n;i++)//初始化 有一种后驱的感觉
        for(int j=1;j<=n;j++)
            path[i][j]=j;

    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            {
                int temp=dist[i][k]+dist[k][j]+node[k];
                if(dist[i][j]>temp)
                {
                    dist[i][j]=temp;
                    path[i][j]=path[i][k];
                }
                if(dist[i][j]==temp)
                {
                    if(path[i][j]>path[i][k])
                        path[i][j]=path[i][k];
                }
            }
}

int main()
{
    int a,be,en;
    while(scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&a);
                if(a!=-1) dist[i][j]=a;
                else dist[i][j]=INF;
            }
        for(int i=1;i<=n;i++) scanf("%d",&node[i]);

        floyd();

        int kcase=0;
        while(1)
        {
            if(kcase!=0) printf("\n");
            kcase++;
            scanf("%d%d",&be,&en);
            if(be==-1&&en==-1) break;
            printf("From %d to %d :\n",be,en);
            printf("Path: ");
            printf("%d",be);

            int temp=be;
            while(temp!=en)
            {
                printf("-->%d",path[temp][en]);
                temp=path[temp][en];
            }
            printf("\n");

            printf("Total cost : %d\n",dist[be][en]);

        }
     }
    return 0;
}



接下来是spfa的做法。


又提交了20+WA

本来就是想练一下输出前驱,结果。。。 某个地方竟然犯了一个我没想到的错。

首先是比较前面结点字典序时,应该从头开始。然后就是这个我会记一辈子的错了。。


邻接表做法

#include 
#include 
#include 
#include 
#include 
using namespace std;

const int maxn=10005,INF=10000000;

queue q;
bool inq[maxn*2];
int first[maxn*2];
int next[maxn*2];
int p[maxn];
int u[maxn*2],v[maxn*2],w[maxn*2],d[maxn*2];
int str1[maxn],str2[maxn];
int n,m;
int map[maxn][maxn];
int node[maxn];
int dis[maxn];

void spfa(int be)
{
    while(!q.empty()) q.pop();
    for(int i=0;id[x]+w[e])
          {
              d[v[e]]=d[x]+w[e];
              p[v[e]]=x;
              if(!inq[v[e]])
              {
                  inq[v[e]]=true;
                  q.push(v[e]);
              }
          }
          else if(d[v[e]]==d[x]+w[e])//这一块遍历前趋没问题
          {
              int l1=0,l2=0;

              int temp=v[e];
              while(temp!=be)
              {
                  str1[l1++]=temp;
                  temp=p[temp];
              }

              temp=x;
              while(temp!=be)
              {
                  str2[l2++]=temp;
                  temp=p[temp];
              }

              for(int i=l1-1,j=l2-1;i>=0&&j>=0;i--,j--)
              {
                  if(str1[i]>str2[j])
                  {
                      p[v[e]]=x;
                      break;
                  }
                  else if(str1[i]",a+1,b+1,a+1);
             for(int i=l-1;i>=0;i--){
                 printf("%d-->",dis[i]+1);
             }
             printf("%d\nTotal cost : %d\n\n",b+1,d[b]-node[b]);
         }
    }
    return 0;
}


哈哈,想了终于明白这个地方 temp=v[e]了。

比如1 2 4 还有一个是1 2 3 4 显然第二种比第一种字典序更靠前。

但自己不是temp=v[e]的话就少了这种情况。

如果是1 2 3 4和1 2 4则可以成功。

自己可以生成一个案例。

终于明白,呵~~~~~~~~~~~~

错这么多次也是值得的,至少自己验证了模板和自己某些方面的不严谨性。

 

4
-1 1 -1 -1
1 -1 2 3
-1 2 -1 1
-1 3 1 -1
0 0 0 0
1 4
From 1 to 4 :
Path: 1-->2-->4
Total cost : 4

这个样例是错的。   神一般的解放呀

你可能感兴趣的:(ACM)