Bzoj2763 分层图最短路

Bzoj2763

题意:在图上,有k次机会可以直接通过一条边而不计算边权,问起点与终点之间的最短路径。

思路:类似于求最短路经,但由于可以有k次机会不计算边权,所以需要加上一维状态表示用了几次机会。

Code:

#include 
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e4+66;
int s , t ; 
int n , m , k ; 
struct Node{
    int v ;
    int dis ; 
    int level ; 
    bool operator < ( const Node &x ) const{
        return x.dis < dis ; 
    }
};
std::vector G[AX];
priority_queue q; 
bool vis[AX][20];
int dis[AX][20];
void dji(){
    while( !q.empty() ){
        Node tmp = q.top();
        q.pop();
        int v = tmp.v;
        int level = tmp.level; 
        if( vis[v][level] ) continue;
        vis[v][level] = true ;
        for( int i = 0 ; i < G[v].size() ; i++ ){
            int to = G[v][i].v ;
            int w = G[v][i].dis;
            if( w + dis[v][level] < dis[to][level] ){
                dis[to][level] = w + dis[v][level];
                q.push((Node){to,dis[to][level],level});
            }
            if( level < k && dis[v][level] < dis[to][level+1] ){
                dis[to][level+1] = dis[v][level];
                q.push((Node){to,dis[to][level+1],level+1});
            }
        }
    }
}

int main(){
    int x , y , w ; 
    scanf("%d%d%d",&n,&m,&k);
    scanf("%d%d",&s,&t);
    for( int i = 0 ; i <= n ; i++ ) G[i].clear();
    for( int i = 0 ; i < m ; i++ ){
        scanf("%d%d%d",&x,&y,&w);
        G[x].push_back((Node){y,w});
        G[y].push_back((Node){x,w});
    }
    memset( vis , false , sizeof(vis) ) ;
    for( int i = 0 ; i < n ; i++ ){
        for( int j = 0 ; j <= k ; j++ ){
            dis[i][j] = INF;
        }
    }
    dis[s][0] = 0 ; 
    q.push((Node){s,0,0});
    dji();
    int res = dis[t][0];
    for( int i = 1 ; i <= k ; i++ ){
        res = min( res , dis[t][i] );
    }
    printf("%d\n",res);
    return 0 ; 
}

你可能感兴趣的:(最短路,DP)