分析:
反向建一颗最短路树(即根节点时目标节点)
每条非最短路径,一定可以表示为一些非树边的有序集合。
然后可以通过依次拓展的方式,来得到第K大。
每次拓展有两种方式(假设最后一条非树边为[u,v]):
1、把最后一条边替换为:从u到根的路径上,比其大的最小的非树边。
2、把v到根的路径上最小的一条非树边加在序列最后。
实现可以用可持久化可并堆完成。
例题:HDU5960
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define SF scanf
#define PF printf
#define MAXN 400010
#define INF 1e15
using namespace std;
typedef long long ll;
int s,t;
vector<int> a[MAXN],b[MAXN],wa[MAXN],wb[MAXN];
int fa[MAXN];
int st[MAXN],d[MAXN];
ll dis[MAXN];
struct node *NIL;
struct node{
ll val;
int dis,to;
node *ch[2];
}Tree[MAXN*40];
node *ncnt=Tree,*rt[MAXN];
node *Newnode(int to,int val){
ncnt++;
ncnt->to=to,ncnt->val=val;
ncnt->ch[0]=ncnt->ch[1]=NIL;
ncnt->dis=0;
return ncnt;
}
void add_edge(int x,int y,int val){
a[x].push_back(y);
b[y].push_back(x);
wa[x].push_back(val);
wb[y].push_back(val);
d[x]++;
}
int n,k;
void init(){
NIL=Tree;
NIL->ch[0]=NIL->ch[1]=NIL;
s=n+1,t=3*n+1;
int c0,c1,co;
ncnt=NIL;
for(int i=1;i<=t;i++){
dis[i]=INF;
a[i].clear();
b[i].clear();
wa[i].clear();
wb[i].clear();
}
for(int i=1;i<=n;i++){
SF("%d%d%d",&c0,&c1,&co);
add_edge(n+i,i,-c0);
add_edge(2*n+i,i,-c1);
if(i!=n){
add_edge(n+i,n+i+1,0);
add_edge(2*n+i,2*n+i+1,0);
if(co)
add_edge(i,2*n+i+1,0);
else
add_edge(i,n+i+1,0);
}
else
add_edge(n,t,0),add_edge(2*n,t,0),add_edge(3*n,t,0);
}
}
void prepare(){
int top=1;
st[top]=t;
dis[t]=fa[t]=0;
while(top){
int x=st[top--];
for(int i=0;i<int(b[x].size());i++){
int u=b[x][i];
if(dis[u]>dis[x]+wb[x][i]){
dis[u]=dis[x]+wb[x][i];
fa[u]=x;
}
d[u]--;
if(d[u]==0)
st[++top]=u;
}
}
}
int tot;
node *merge(node *x,node *y){
if(x==NIL) return y;
if(y==NIL) return x;
if(x->val > y->val)
swap(x,y);
node *nx=++ncnt;
*nx=*x;
nx->ch[1]=merge(nx->ch[1],y);
if(nx->ch[1]->dis > nx->ch[0]->dis)
swap(nx->ch[1],nx->ch[0]);
nx->dis=nx->ch[1]->dis+1;
return nx;
}
void dfs(int x){
rt[x]=rt[fa[x]];
for(int i=0;i<int(a[x].size());i++)
if(a[x][i]!=fa[x])
rt[x]=merge(Newnode(a[x][i],dis[a[x][i]]-dis[x]+wa[x][i]),rt[x]);
for(int i=0;i<int(b[x].size());i++)
if(fa[b[x][i]]==x)
dfs(b[x][i]);
}
priority_queue<pair<ll,node *>,vector<pair<ll,node *> >,greater<pair<ll,node *> > >q;
int main(){
int Cas;
SF("%d",&Cas);
while(Cas--){
SF("%d%d",&n,&k);
k--;
init();
prepare();
rt[0]=NIL;
dfs(t);
if(k==0){
PF("%lld\n",-dis[s]);
continue;
}
if(rt[s]!=NIL)
q.push(make_pair(dis[s]+rt[s]->val,rt[s]));
while(--k&&q.size()){
node *x=q.top().second;
ll val=q.top().first;
q.pop();
int v=x->to;
if(rt[v]!=NIL)
q.push(make_pair(val+rt[v]->val,rt[v]));
if(x->ch[0]!=NIL)
q.push(make_pair(val- x->val + x->ch[0]->val,x->ch[0]));
if(x->ch[1]!=NIL)
q.push(make_pair(val- x->val + x->ch[1]->val,x->ch[1]));
}
if(q.empty())
PF("-1\n");
else
PF("%lld\n",-q.top().first);
while(!q.empty())
q.pop();
}
}