zoukankan      html  css  js  c++  java
  • HDU

    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
    ",ans[cur[i]]);
            }
        }
        return 0;
    }
    
    
    越自律,越自由
  • 相关阅读:
    [工具推荐]005.Axure RP Pro 7.0模拟C#TAB控件
    [安卓基础] 008.Android中的显示单位
    [JavaWeb基础] 008.Spring初步配置
    [批处理教程之Shell]002.Linux 常用命令大全
    [注]新手学习编程的最佳方式是什么?
    [C#打包部署教程]001.VS2012 + InstallShield
    [站点推荐]001.学习新技能的37个最佳网站(The 37 Best Websites To Learn Something New)
    程序员如何像写代码一样找女朋友
    [工具-006] C#如何模拟发包登录
    [Linux系统] (1)常用操作(CentOS 7.x)
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13635445.html
Copyright © 2011-2022 走看看