【堆优化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 :\n",S,T);
 88     printf("Path: ");
 89     while (i>=1)
 90     {
 91         printf("%d",s1[i--]);
 92         if (i!=0) printf("-->");
 93     }
 94     printf("\nTotal cost : %d\n\n",(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("\n");
33         
34     }
35     
36     for (int i=0;i<n;i++)
37     {
38         printf("%d ",(rand()%n));
39     } 
40         
41     printf("\n");
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\n",temp1,temp2);
48         
49     } 
50         
51     printf("%d %d\n",-1,-1);
52     printf("%d\n",0);
53     
54     fclose(stdout);
55     return 0;
56 }

 

posted @ 2016-11-13 18:25  iiyiyi  阅读(514)  评论(0编辑  收藏  举报