【HDOJ】1688 Sightseeing

Dijkstra求解次短路径,使用cnt和dis数组记录最小、次小的个数和长度。重写更新操作。

  1 /* 1688 */
  2 #include <iostream>
  3 #include <string>
  4 #include <map>
  5 #include <queue>
  6 #include <set>
  7 #include <vector>
  8 #include <algorithm>
  9 #include <cstdio>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <climits>
 13 #include <cctype>
 14 using namespace std;
 15 
 16 #define MAXN 1005
 17 #define INF  0x3f3f3f3f
 18 
 19 typedef struct Edge_t {
 20     int v, w;
 21     Edge_t() {}
 22     Edge_t(int u, int ww) {
 23         v = u; w = ww;
 24     }
 25 } Edge_t;
 26 
 27 vector<Edge_t> vc[MAXN];
 28 bool visit[MAXN][2];
 29 int dis[MAXN][2];
 30 int cnt[MAXN][2];
 31 int n, m;
 32 
 33 void init() {
 34     int i;
 35     
 36     for (i=1; i<=n; ++i)
 37         vc[i].clear();
 38     memset(cnt, 0, sizeof(cnt));
 39 }
 40 
 41 int dijkstra(int s, int f) {
 42     int i, j, k, tmp, r;
 43     int u, v, w, mmin;
 44     int ret = 0;
 45     Edge_t e;
 46     
 47     memset(visit, false, sizeof(visit));
 48     memset(dis, 0x3f, sizeof(dis));
 49     dis[s][0] = 0;
 50     cnt[s][0] = 1;
 51     
 52     for (r=0; r<n*2; ++r) {
 53         mmin = INF;
 54         u = -1;
 55         for (j=1; j<=n; ++j) {
 56             if (!visit[j][0] && dis[j][0]<mmin) {
 57                 mmin = dis[j][0];
 58                 u = j;
 59                 k = 0;
 60             } else if  (!visit[j][1] && dis[j][1]<mmin) {
 61                 mmin = dis[j][1];
 62                 u = j;
 63                 k = 1;
 64             }
 65         }
 66         if (u == -1)
 67             break;
 68         visit[u][k] = true;
 69         for (i=0; i<vc[u].size(); ++i) {
 70             e = vc[u][i];
 71             v = e.v;
 72             w = e.w;
 73             tmp = w + dis[u][k];
 74             if (tmp < dis[v][0]) {
 75                 dis[v][1] = dis[v][0];
 76                 cnt[v][1] = cnt[v][0];
 77                 dis[v][0] = tmp;
 78                 cnt[v][0] = cnt[u][k];
 79             } else if (tmp == dis[v][0]) {
 80                 cnt[v][0] += cnt[u][k];
 81             } else if (tmp < dis[v][1]) {
 82                 dis[v][1] = tmp;
 83                 cnt[v][1] = cnt[u][k];
 84             } else if (tmp == dis[v][1]) {
 85                 cnt[v][1] += cnt[u][k];
 86             }
 87         }
 88     }
 89     
 90     ret += cnt[f][0];
 91     if (dis[f][0]+1 == dis[f][1])
 92         ret += cnt[f][1];
 93     return ret;
 94 }
 95 
 96 int main() {
 97     int t;
 98     int i, j, k;
 99     Edge_t e;
100     
101     #ifndef ONLINE_JUDGE
102         freopen("data.in", "r", stdin);
103         freopen("data.out", "w", stdout);
104     #endif
105     
106     scanf("%d", &t);
107     while (t--) {
108         scanf("%d %d", &n, &m);
109         init();
110         while (m--) {
111             scanf("%d %d %d", &i, &e.v, &e.w);
112             vc[i].push_back(e);
113         }
114         scanf("%d %d", &i, &j);
115         k = dijkstra(i, j);
116         printf("%d\n", k);
117     }
118     
119     return 0;
120 }

 

转载于:https://www.cnblogs.com/bombe1013/p/4379184.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值