POJ 3463 && HDU 1688 Sightseeing 次短路

30 篇文章 0 订阅

这道题就是给出有向图和起点s重点t,求出s到t的次短路个数+最短路个数,注意,次短路总和如果比最短路总和+1要大的话,就只要算最短路个数。

由于不难, 所以直接上代码。

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std ;
const int maxn = 1010, maxm = 10010 ;
const int zhf = 1000000000 ;
inline void Read ( int &x ) { // 养成读入输出优化的习惯了。。。。
    char c = getchar() ; bool f = 0 ; x = 0 ;
    while ( !isdigit(c) ) {
        if ( c == '-' ) f = 1 ;
        c = getchar() ;
    }
    while ( isdigit(c) ) {
        x = 10 * x + c - '0' ;
        c = getchar() ;
    } if (f) x = -x ;
}
inline void Print ( int x ) {
    int len = 0 , s[20] = {0} ;
    if ( x == 0 ) {
        putchar('0') ;
        return ; 
    } if ( x < 0 ) {
        x = -x ;
        putchar('-') ;
    }
    while (x) {
        s[++len] = x % 10 ;
        x /= 10 ;
    }
    while (len) putchar ( s[len--] + '0' ) ;
}
int to[maxm], e, n, m, be[maxn], nxt[maxm], w[maxm], d[maxn][2], cnt[maxn][2] ;
bool vis[maxn][2] ;
//后面的[2],[0]表示最短路中,[1]表示次短路中
void add ( int x, int y, int z ) {
    to[++e] = y ;
    nxt[e] = be[x] ; 
    be[x] = e ;
    w[e] = z ;
}//链式前向星
void init() {
    int i ;
    e = 0 ;
    for ( i = 0 ; i < maxn ; i ++ ) 
        to[i] = be[i] = nxt[i] = w[i] = vis[i][0] = vis[i][1] = cnt[i][1] = cnt[i][0] = 0,
        d[i][1] = d[i][0] = zhf ;
    for ( i = maxn ; i < maxm ; i ++ ) 
        to[i] = nxt[i] = w[i] = 0 ;
}//初始化
int dijkstra ( int st, int end ) {
    int i, j, k ; // Kind
    d[st][0] = 0 ; cnt[st][0] = 1 ;
    for ( i = 1 ; i <= n << 1 ; i ++ ) {
        int minn = zhf , u = -1 ;
        for ( j = 1 ; j <= n ; j ++ ) 
            for ( int flag = 0 ; flag <= 1 ; flag ++ ) 
                if ( !vis[j][flag] && d[j][flag] < minn ) {
                    u = j ; 
                    minn = d[j][flag] ;
                    k = flag ;
                }
        if ( u == -1 ) break ;
        vis[u][k] = 1 ;
        for ( j = be[u] ; j ; j = nxt[j] ) {
            int v = to[j] ;
            int wei = d[u][k] + w[j] ;
            if ( wei < d[v][0] ) { // 更新最短路 
                d[v][1] = d[v][0] ;
                cnt[v][1] = cnt[v][0] ;
                d[v][0] = wei ;
                cnt[v][0] = cnt[u][k] ;
            } else if ( wei == d[v][0] ) { //等于最短路
                cnt[v][0] += cnt[u][k] ;
            } else if ( wei < d[v][1] ) { //更新次短路
                d[v][1] = wei ;
                cnt[v][1] = cnt[u][k] ;
            } else if ( wei == d[v][1] ) //等于次短路
                cnt[v][1] += cnt[u][k] ;
        }
    }
    int res = cnt[end][0] ;
    if ( d[end][1] - 1 == d[end][0] ) //是否需要加入次短路数量
        res += cnt[end][1] ;
    return res ;
}
int main () {
    int i, j, k, st, end, x, y, z, t ;
    Read(t) ; 
    while ( t -- ) {
        init() ;
        Read(n) ; Read(m) ; 
        for ( i = 1 ; i <= m ; i ++ ) {
            Read(x) ; Read(y) ; Read(z) ;
            add ( x, y, z ) ; //有向图
        } Read(st) ; Read (end) ;
        Print ( dijkstra( st, end ) ) ;
        putchar('\n');
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值