【HDU】5960 Subsequence 【可持久化左偏樹維護K短路】

題目鏈接:Subsequence

題目分析:建出最短路圖,將最短路圖的邊全部反向,求出t 出發的任意一棵最短路樹(其中d[i]ti 的最短路)。然後考慮i 的原向邊出邊表,任意不在最短路樹上的邊<i,j> ,設其權值爲d[j]d[i]+cost(i,j) ,那麼所有從i 出發到t 的路徑均可以看成一堆非樹邊+一堆樹邊,其路徑長度等價於d[i]+ 經過的所有非樹邊權值。因此,所有不在最短路上的邊均加入i 的堆內,然後便可以維護從s 出發到t 的第k 短路徑。i 的堆由其最短路樹上的父親加上自己的出邊構成,可用可持久化左偏樹實現。

吐槽,先是對着定義yy了可持久化二項堆,然後發現不好搞這個k短路,然後找了左偏樹的定義,對着yy了20分鐘寫出了可持久化左偏樹,然後過了poj2449後就1A了這個題。

#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std ;

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

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

const int MAXN = 150005 ;
const int MAXE = 300005 ;
const LL INF = 1e18 ;

namespace Leftist_Tree {
    struct Node {
        int l , r , x , h ;
        LL val ;
    } T[MAXN * 40] ;
    int Root[MAXN] , 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 ) ;
    }
}

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

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

void topo () {
    queue < int > q ;
    q.push ( t ) ;
    d[t] = p[t] = 0 ;
    while ( !q.empty () ) {
        int u = q.front () ;
        q.pop () ;
        for ( int i = 0 ; i < E[u].size () ; ++ i ) {
            int v = E[u][i].st , c = E[u][i].ed ;
            if ( d[v] > d[u] + c ) {
                d[v] = d[u] + c ;
                p[v] = u ;
            }
            if ( 0 == -- in[v] ) q.push ( v ) ;
        }
    }
}

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

void solve () {
    scanf ( "%d%d" , &n , &k ) ;
    s = n + 1 ;
    t = 3 * n + 1 ;
    for ( int i = 1 ; i <= t ; ++ i ) {
        in[i] = vis[i] = 0 ;
        G[i].clear () ;
        E[i].clear () ;
        d[i] = INF ;
    }
    for ( int i = 1 ; i <= n ; ++ i ) {
        int x , y , c ;
        scanf ( "%d%d%d" , &x , &y , &c ) ;
        addedge ( i + n , i , -x ) ;
        addedge ( i + n + n , i , -y ) ;
        if ( i < n ) {
            addedge ( i + n , i + n + 1 , 0 ) ;
            addedge ( i + n + n , i + n + n + 1 , 0 ) ;
            if ( !c ) addedge ( i , i + n + 1 , 0 ) ;
            else addedge ( i , i + n + n + 1 , 0 ) ;
        }
    }
    addedge ( n * 1 , t , 0 ) ;
    addedge ( n * 2 , t , 0 ) ;
    addedge ( n * 3 , t , 0 ) ;
    topo () ;
    if ( k == 1 ) {
        printf ( "%lld\n" , -d[s] ) ;
        return ;
    }
    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 -- ) {
        pli u = q.top () ;
        q.pop () ;
        if ( k == 1 ) {
            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 T ;
    scanf ( "%d" , &T ) ;
    while ( T -- ) solve () ;
    return 0 ;
}

壓縮後代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int>pli;
typedef pair<int,int>pii;
#define clr(a,x) memset(a,x,sizeof a)
#define st first
#define ed second
const int MAXN=150005,MAXE=300005;
const LL INF=1e18;
namespace Fast_Read{
    const int SIZE=1<<16;
    char buf[SIZE],c;
    int l=0,r=0;
    inline char readchar(){
        if(l==r){l=0,r=fread(buf,1,SIZE,stdin);}
        return buf[l++];
    }
    inline void scanf(int&x){
        while((c=readchar())<48);
        x=c-48;
        while((c=readchar())>47)x=x*10+c-48;
    }
}
namespace Leftist_Tree{
    struct Node{int l,r,x,h;LL val;}T[MAXN*40];
    int Root[MAXN],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);}
}
using namespace Leftist_Tree;
vector<pii>G[MAXN],E[MAXN];
int vis[MAXN],in[MAXN],p[MAXN],s,t,n,k;
LL d[MAXN];
void addedge(int u,int v,int c){G[u].push_back(pii(v,c)),E[v].push_back(pii(u,c)),in[u]++;}
void topo(){
    queue<int>q;
    for(q.push(t),d[t]=p[t]=0;!q.empty();q.pop()){
        for(int i=0,u=q.front();i<E[u].size();++i){
            int v=E[u][i].st,c=E[u][i].ed;
            if(d[v]>d[u]+c)d[v]=d[u]+c,p[v]=u;
            if(!--in[v])q.push(v);
        }
    }
}
void dfs(int u){
    if(vis[u])return;
    vis[u]=1;
    if(p[u])Root[u]=Root[p[u]];
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i].st;
        if(d[v]!=INF&&p[u]!=v)insert(Root[u],d[v]-d[u]+G[u][i].ed,v);
    }
    for(int i=0;i<E[u].size();++i)if(p[E[u][i].st]==u)dfs(E[u][i].st);
}
void solve(){
    Fast_Read::scanf(n);
    Fast_Read::scanf(k);
    //scanf("%d%d",&n,&k);
    s=n+1,t=3*n+1;
    for(int i=1;i<=t;++i)in[i]=vis[i]=0,G[i].clear(),E[i].clear(),d[i]=INF;
    for(int i=1,x,y,c;i<=n;++i){
        Fast_Read::scanf(x);
        Fast_Read::scanf(y);
        Fast_Read::scanf(c);
        //scanf("%d%d%d",&x,&y,&c);
        addedge(i+n,i,-x);
        addedge(i+n+n,i,-y);
        if(i<n){
            addedge(i+n,i+n+1,0);
            addedge(i+n+n,i+n+n+1,0);
            if(!c)addedge(i,i+n+1,0);
            else addedge(i,i+n+n+1,0);
        }
    }
    addedge(n*1,t,0),addedge(n*2,t,0),addedge(n*3,t,0);
    topo();
    if(k==1){printf("%lld\n",-d[s]);return;}
    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--){
        pli u=q.top();q.pop();
        if(k==1){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 T;
    Fast_Read::scanf(T);
    //scanf("%d",&T);
    while(T--)solve();
    return 0;
}
發佈了718 篇原創文章 · 獲贊 37 · 訪問量 64萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章