k短路模板 整理

题目列表:
1. https://cn.vjudge.net/problem/HDU-5960
2. hdu6181 第k短路 – 双向边
3. poj 2449 最裸的模板
4. 2018-沈阳网络赛-D-K短路 https://nanti.jisuanke.com/t/31445

总结 :除了第一题,其他的都是很裸的模板题,所以只介绍第一题。
其中第2题是求1-n次短路,且是双向边
第2题直接求k短路,没有的话输出-1,单向边
第4题判断k短路是否小于等于T,单向边
第一题 题意:给定n条边 每条边(cost,cost2,color)
color只有0,1 现在让你从这些边中求一个子序列,这个子序列的权值
是这样计算的,假设你选了h个点,从1-h,一开始 now = 0
if now=0 ans+=cost
else ans+=cost2 然后now = 该条边的color

建图参考
我是看上面这篇博客看懂的,但是上面这篇博客里有一些错误,
首先把每一个点拆成3个点,i,i+n,i+n+n
然后i+n层作为cost层,i+n+n作为cost2层
如果i!=n 每个点都向当前点的下一个点进行转移连一条权值为0的边,
层与层之间的转移通过i层进行转移,通过color取值向cost层和cost2层进行连边
最后每一层的终点都向终点连一条权值为0的边
由于一开始now = 0,所以起点是点n+1

出处:无敌k短路

#include 
#include 
#include 
#include 
using namespace std ;

typedef long long LL ;
typedef pair < int, int > pii ;
typedef pair < LL, int > pli ;
typedef unsigned long long ULL ;

#define clr( a , x ) memset ( a , x , sizeof a )
#define st first
#define ed second

const int MAXN = 100005 ;
const int BLOCK = 22 ;
const LL INF = 1e18 ;

namespace Leftist_Tree
{
struct Node
{
    int l, r, x, h ;
    LL val ;
} T[MAXN * 200] ;
int Root[MAXN] ;
int node_num ;
int newnode ( const Node& o )
{
    T[node_num] = o ;
    return node_num ++ ;
}
void init ()
{
    node_num = 1 ;
    T[0].l = T[0].r = T[0].x = T[0].h = 0 ;
    T[0].val = INF ;
}
int merge ( int x, int y )
{
    if ( !x ) return y ;
    if ( T[x].val > T[y].val ) swap ( x, y ) ;
    int o = newnode ( T[x] ) ;
    T[o].r = merge ( T[o].r, y ) ;
    if ( T[T[o].l].h < T[T[o].r].h ) swap ( T[o].l, T[o].r ) ;
    T[o].h = T[T[o].r].h + 1 ;
    return o ;
}
void insert ( int& x, LL val, int v )
{
    int o = newnode ( T[0] ) ;
    T[o].val = val, T[o].x = v ;
    x = merge ( x, o ) ;
}
void show ( int o )
{
    printf ( "%d %lld %lld %lld\n", o, T[o].val, T[T[o].l].val, T[T[o].r].val ) ;
    if ( T[o].l ) show ( T[o].l ) ;
    if ( T[o].r ) show ( T[o].r ) ;
}
}

using namespace Leftist_Tree ;
vector < pii > G[MAXN], E[MAXN] ;
int vis[MAXN] ;
int in[MAXN], p[MAXN] ;
LL d[MAXN] ;
int s, t ;
int n, m, k ;

void addedge ( int u, int v, int c )
{
    G[u].push_back ( pii ( v, c ) ) ;
    E[v].push_back ( pii ( u, c ) ) ;
}

void dij ()
{
    priority_queue < pli > q ;
    d[t] = 0 ;
    q.push ( pli ( 0, t ) ) ;
    while ( !q.empty () )
    {
        int u = q.top ().ed ;
        q.pop () ;
        if ( vis[u] ) continue ;
        vis[u] = 1 ;
        for ( int i = 0 ; i < E[u].size () ; ++ i )
        {
            int v = E[u][i].st ;
            if ( d[v] > d[u] + E[u][i].ed )
            {
                p[v] = u ;
                d[v] = d[u] + E[u][i].ed ;
                q.push ( pli ( -d[v], v ) ) ;
            }
        }
    }
}

void dfs ( int u )
{
    if ( vis[u] ) return ;
    vis[u] = 1 ;
    if ( p[u] ) Root[u] = Root[p[u]] ;
    int flag = 1 ;
    for ( int i = 0 ; i < G[u].size () ; ++ i )
    {
        int v = G[u][i].st ;
        if ( d[v] == INF ) continue ;
        if ( p[u] == v && d[u] == G[u][i].ed + d[v] && flag )
        {
            flag = 0 ;
            continue ;
        }
        LL val = d[v] - d[u] + G[u][i].ed ;
        insert ( Root[u], val, v ) ;
    }
    for ( int i = 0 ; i < E[u].size () ; ++ i )
    {
        if ( p[E[u][i].st] == u ) dfs ( E[u][i].st ) ;
    }
}

void solve ()
{
    for ( int i = 1 ; i <= n ; ++ i )
    {
        G[i].clear () ;
        E[i].clear () ;
        d[i] = INF ;
        vis[i] = 0 ;
        p[i] = 0 ;
    }
    for ( int i = 0 ; i < m ; ++ i )
    {
        int u, v, c ;
        scanf ( "%d%d%d", &u, &v, &c ) ;
        addedge ( u, v, c ) ;
        addedge ( v, u, c ) ;
    }
    //scanf ( "%d%d%d", &s, &t, &k ) ;
    s = 1;
    t = n;
    k = 2;
    dij () ;
    if ( d[s] == INF )
    {
        printf ( "-1\n" ) ;
        return ;
    }
    if ( s != t ) -- k ;
    if ( !k )
    {
        printf ( "%lld\n", d[s] ) ;
        return ;
    }
    for ( int i = 1 ; i <= n ; ++ i )
    {
        vis[i] = 0 ;
    }
    init () ;
    Root[t] = 0 ;
    dfs ( t ) ;
    priority_queue < pli, vector < pli >, greater < pli > > q ;
    if ( Root[s] ) q.push ( pli ( d[s] + T[Root[s]].val, Root[s] ) ) ;
    while ( k -- )
    {
        if ( q.empty () )
        {
            printf ( "-1\n" ) ;
            return ;
        }
        pli u = q.top () ;
        q.pop () ;
        if ( !k )
        {
            printf ( "%lld\n", u.st ) ;
            return ;
        }
        int x = T[u.ed].l, y = T[u.ed].r, v = T[u.ed].x ;
        if ( Root[v] ) q.push ( pli ( u.st + T[Root[v]].val, Root[v] ) ) ;
        if ( x ) q.push ( pli ( u.st + T[x].val - T[u.ed].val, x ) ) ;
        if ( y ) q.push ( pli ( u.st + T[y].val - T[u.ed].val, y ) ) ;
    }
}

int main ()
{
    int TT;
    scanf("%d",&TT);
    while ( TT-- )
    {

        scanf ( "%d%d", &n, &m );
        solve();
    }
    return 0 ;
}

分层最短路建图
https://blog.csdn.net/GYH0730/article/details/82289927

你可能感兴趣的:(2018ACM训练题目+思考)