Minimum Transport Cost hdu 1385(最短路 + 路径保存 + stack)

/*
 突然发现hdu的oj数据很强大,在zoj可以过的代码,在hoj就wrong 开始让我有点纳闷
 题目很简单就是路劲的保存有点麻烦,最麻烦的是字典序那个
 这几天题目虽然做的很少,而且所有的代码基本都是自己一个一敲出来的,很少一出错就baidu之类的
 鉴戒是要有的,可是。。。。这个暑假只AC
*/

#include <iostream>
#include <cstdio>
#include <queue>
#include <stack>//stack 是好东西啊
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX = 0x3ffffff;
const int N = 1005;
int cost[N][N];
int path[N];
int c1[N];
int c2[N];
int dis[N];
int v[N];
bool hash[N];
int n;

void small(int start, int j, int pre)
{//这里差不都是xwc的方法
 stack<int>s;
 int len1 = 0, len2 = 0;
 int tt = j;
 while(tt != start)
 {
  s.push(tt);
  tt = path[tt];
 }
 s.push(start);
 while(!s.empty())
 {
  c1[len1++] = s.top();
  s.pop();
 }
 s.push(j);
 //s.push(pre);
 tt = pre;
 while(tt != start)
 {
  s.push(tt);
  tt = path[tt];
 }
 s.push(start);
 while(!s.empty())
 {
  c2[len2++] = s.top();
  s.pop();
 }
 int min1 = min(len1 ,len2);
 for(int i = 0; i < min1; i++)
 {
  if(c1[i] == c2[i])
   continue;
  else if(c1[i] > c2[i])
   path[j] = pre;
  else
   break;
 }
 //if()

}

void Dijsktra(int start, int end)
{
 int i, j, k;
 memset(hash, false, sizeof(hash));
 for(i = 1; i <= n; i++)
 {
  dis[i] = cost[start][i];
  path[i] = start;
  
 }
 dis[start] = 0;
 hash[start] = true;
 for(i = 1; i <= n; i++)
 {
  int d = MAX;
  k = start;
  for(j = 1; j <= n; j++)
  {
   if(!hash[j] && dis[j] < d)
   {
    k = j;
    d = dis[j];
   }
  }
  hash[k] = true;
  if( MAX == dis[k])
   break;
  for(j = 1; j <= n; j++)
  {
   if(!hash[j] && dis[j] > dis[k] + cost[k][j] + v[k] )
   {
    dis[j] = dis[k] + cost[k][j] + v[k];
    //if(k < path[j])
    path[j] = k;

   }//如果路劲相等输出字典序最小的
   else if(!hash[j] && dis[j] == dis[k] + cost[k][j] + v[k])
   {//这里没有加hash[j] 就在hdu oj wrong 在zoj就过了,忒假了
    small(start, j, k);
   }
  }
 }

 printf("From %d to %d :/n", start, end);
 stack <int> s;
 //s.push(end);
 //int tt = path[end];
 int tt = end;
 while(tt != start)
 {
  s.push(tt);
  tt = path[tt];
 }
 s.push(start);
 printf("Path: ");
 int e = s.top();
 s.pop();
 printf("%d", e);
 while(!s.empty())
 {
  int e = s.top();
  s.pop();
  printf("-->%d", e);
 }
 
 printf("/n");
 /*
 for(i = len ; i >= 0; i--)
 {
 if(i != 0)
 printf("%d-->", ctrl[i]);
 else
 printf("%d/n", ctrl[i]);
 }
 */
 //for(i = 1; i <= n; i++)
 //printf("%d ", path[i]);
 printf("Total cost : %d/n/n", dis[end]);

}

int main()
{
 //int df[N];
 while(scanf("%d", &n) != EOF && n)
 {
  int i, j, k;
  for(i = 1; i <= n; i++)
  for(j = 1; j <= n; j++)
  {
   scanf("%d", &cost[i][j]);
   if(cost[i][j] == -1)
    cost[i][j] = MAX;
  }
   for(i = 1; i <= n; i++)
    scanf("%d", &v[i]);
   int a, b;
   while(1)
   {
    scanf("%d %d", &a, &b);
    if(a == -1 && b == -1)
     break;
    Dijsktra(a ,b);
   }

 }
 return 0;
}
/*
4
0 2 -1 1
2 0 2 -1
-1 2 0 1
1 -1 1 0
9 2 9 4
1 3
From 1 to 3 :
Path: 1-->2-->3
Total cost : 6
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值