HDU - 6705 path (求图上不固定起终点的第k短路)
path hdu-6705
题意:给你一幅有向图,给你q个数k ,问你在这幅图上第k短的路径有多长。
思路:首先有q个询问,且没有出现修改操作,考虑离线处理。然后我们可以用一个vector储存所有的边。并把每个节点的出边按从小到大排序。接下来求出所有询问的最大值maxk,然后我们只要求第1~maxk的短路即可。然后先把所有边都存入一个set,并且这个set是按照路径长短排序的。接下来保证这个set里的元素有maxk个,然后用类似于Djikstra求最短路的方法不断去set中的内容即可,第i次从set的头部弹出的就是第i短路。
代码:
const int maxn=5e5+5;
ll ans[maxn];
int n,m,k,cur[maxn],cnt=0;
struct node{
int v;ll w;
node (int v = 0, int w = 0): v(v), w(w) {}
bool operator < (const node &b) const {
return w<b.w;
}
};
vector<node>G[maxn];
struct Edge{
int u,v;
ll w;
int id;
Edge(int u = 0, int v = 0, ll w = 0, int id = 0): u(u), v(v), w(w), id(id) {}
bool operator <(const Edge &b)const{
if(w==b.w){
if(u==b.u){
if(v==b.v){
return id<b.id;
}else{
return v<b.v;
}
}else{
return u<b.u;
}
}else{
return w<b.w;
}
}
bool operator == (const Edge &b) const {
return w == b.w && u == b.u && v == b.v && id == b.id;
}
};
int main()
{
int T;
cin>>T;
while(T--){
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++){
G[i].clear();
}
set<Edge>st;
st.clear();
cnt=0;
for(int i=1;i<=m;i++){
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
G[u].push_back(node(v,w));
st.insert(Edge(u,v,w,++cnt));
}
for(int i=1;i<=n;i++){
sort(G[i].begin(),G[i].end());
}
int maxk=0;
for(int i=1;i<=k;i++){
scanf("%d",&cur[i]);
maxk=max(maxk,cur[i]);
}
while(st.size()>maxk){
st.erase(st.end());
}
for(int i=1;i<=maxk;i++){
Edge now=*st.begin();
st.erase(st.begin());
ans[i]=now.w;
if(i==maxk)break;
int u=now.v;
for(int j=0;j<G[u].size();j++){
int v=G[u][j].v;
ll w=G[u][j].w;
if(st.size()+i<maxk){
st.insert(Edge(u,v,now.w+w,++cnt));
}else{
set<Edge>::iterator it = st.end();
it--;
Edge last=*it;
if(last.w>w+now.w){
st.erase(it);
st.insert(Edge(u,v,w+now.w,++cnt));
}else{
break;
}
}
}
}
for(int i=1;i<=k;i++){
printf("%lld\n",ans[cur[i]]);
}
}
return 0;
}
越自律,越自由