zoukankan      html  css  js  c++  java
  • 【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost

    【题目大意】

    给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案。

    【思路】

    在堆优化Dijkstra中,用pre记录前驱。如果新方案和旧方案相等,比较两个方案的字典序。

    【坑点】

    我先求出了最短路(包括终点要付出代价),输出的时候再减去终点的代价。

    有可能会给出S==T的情况……在这种情况下,最短路就是0,减去代价要变成负数了QAQ所以要特判一下。坑了好几个小时orz

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cstdlib>
      6 #include<cmath>
      7 #include<queue>
      8 #include<vector>
      9 using namespace std;
     10 const int MAXN=2000+50;
     11 const int INF=0x7fffffff;
     12 
     13 struct edge
     14 {
     15     int to,len;
     16 };
     17 
     18 vector<edge> E[MAXN];
     19 priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > pque;
     20 int vis[MAXN],dis[MAXN],pre[MAXN],tax[MAXN];
     21 int s1[MAXN],s2[MAXN],n;
     22 
     23 void addedge(int u,int v,int w)
     24 {
     25     E[u].push_back((edge){v,w});
     26 }
     27 
     28 void init()
     29 {
     30     for (int i=1;i<MAXN;i++) vector<edge>().swap(E[i]);
     31     while (!pque.empty()) pque.pop();
     32     for (int i=1;i<=n;i++)
     33         for (int j=1;j<=n;j++)
     34         {
     35             int aij;
     36             scanf("%d",&aij);
     37             if (aij>=0 && i!=j) addedge(i,j,aij);
     38         }
     39     for (int i=1;i<=n;i++) scanf("%d",&tax[i]);
     40 }
     41 
     42 int compare(int now,int before)
     43 {
     44     memset(s1,0,sizeof(s1));
     45     memset(s2,0,sizeof(s2));
     46     int i=0,j=-1;
     47     s1[0]=before;
     48     while (now!=0) s1[++i]=now,now=pre[now];
     49     while (before!=0) s2[++j]=before,before=pre[before];
     50     for (;i>=0 && j>=0;i--,j--)
     51         if (s1[i]<s2[j]) return 1;
     52             else if (s1[i]>s2[j]) return 0; 
     53     return (s1<s2);
     54 }
     55 
     56 int dijkstra(int S,int T)
     57 {
     58     for (int i=1;i<=n;i++) vis[i]=0,dis[i]=INF,pre[i]=-1;
     59     dis[S]=0,pre[S]=0;
     60     pque.push(pair<int,int>(0,S));
     61     while (!pque.empty())
     62     {
     63         int u=pque.top().second;pque.pop();
     64         vis[u]=1;
     65         for (int i=0;i<E[u].size();i++)
     66         {
     67             int v=E[u][i].to,len=E[u][i].len+tax[v];
     68             if (dis[v]>=dis[u]+len)
     69             {
     70                 if (dis[v]>dis[u]+len)
     71                 {
     72                     dis[v]=dis[u]+len;    
     73                     pre[v]=u;
     74                     pque.push(pair<int,int>(dis[v],v));
     75                 }
     76                 else if (dis[v]==dis[u]+len && compare(u,v)) 
     77                 {
     78                     pre[v]=u;
     79                     pque.push(pair<int,int>(dis[v],v));
     80                 }
     81             }
     82         }
     83     }
     84 
     85     int i=0,now=T;
     86     while (now!=0) s1[++i]=now,now=pre[now];
     87     printf("From %d to %d :
    ",S,T);
     88     printf("Path: ");
     89     while (i>=1)
     90     {
     91         printf("%d",s1[i--]);
     92         if (i!=0) printf("-->");
     93     }
     94     printf("
    Total cost : %d
    
    ",(S==T)?0:dis[T]-tax[T]);
     95     //注意如果S==T的时候,就不要减去tax了,否则会出现负值。 
     96 }
     97 
     98 void solve()
     99 {
    100     int a,b;
    101     while (scanf("%d%d",&a,&b))
    102     {
    103         if (a==-1 && a==b) return;
    104         dijkstra(a,b);
    105     }
    106 }
    107 
    108 int main()
    109 {
    110     while (scanf("%d",&n))
    111     {
    112         if (n==0) break;
    113         init();
    114         solve();
    115     } 
    116     return 0;    
    117 }

    附上随机数据生成:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int main()
     5 {
     6     freopen("samplein.txt", "w", stdout);
     7     srand((unsigned)time(NULL)); 
     8     int n=rand() % 100;
     9     int ne;
    10     cout<<n<<endl;
    11     for (int i=0;i<n;i++)
    12     {
    13         for (int j=0;j<n;j++)
    14         {
    15             if (i==j)
    16             {
    17                 printf("%d",0);
    18             }
    19             else 
    20             {
    21                 if((rand()%n)<(n/5))
    22                 {
    23                     printf("-1");
    24                 }
    25                 else
    26                 { 
    27                     printf("%d",(rand()%(n-1)+1));
    28                 } 
    29             }
    30             printf(" ");
    31         }
    32         printf("
    ");
    33         
    34     }
    35     
    36     for (int i=0;i<n;i++)
    37     {
    38         printf("%d ",(rand()%n));
    39     } 
    40         
    41     printf("
    ");
    42     int tmp=rand()%n;
    43     for (int i=0;i<tmp;i++)
    44     { 
    45         int temp1=(rand()%(n-1)+1);
    46         int temp2=(rand()%(n-1)+1);
    47         printf("%d %d
    ",temp1,temp2);
    48         
    49     } 
    50         
    51     printf("%d %d
    ",-1,-1);
    52     printf("%d
    ",0);
    53     
    54     fclose(stdout);
    55     return 0;
    56 }
  • 相关阅读:
    如何制定自己的博客园皮肤
    Notepad++ PluginManager安装常用插件
    Python进阶5---StringIO和BytesIO、路径操作、OS模块、shutil模块
    Python进阶4---Python的文件IO
    Python进阶3---python类型注解、functools
    dreamweavercs 和dreamweaver cc的區別
    Dreamweaver怎样用Edge Web Fonts功能
    vs code軟件操作
    vscode git設置
    git和svn的區別
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6059437.html
Copyright © 2011-2022 走看看