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;
}

posted @ 2020-09-08 21:06  hachuochuo  阅读(130)  评论(0编辑  收藏  举报