hdu 6705

Posted 19992147orz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 6705相关的知识,希望对你有一定的参考价值。

堆+贪心

超级钢琴的套路

先将每个点的出边按权值大小排序

维护一个四元组$(w, u, v, p)$,表示当前路径长度为$w$,当前边的起点是$u$,终点是$v$,这条边是$u$的出边中排序后的第$p$条边

每次出堆的路径加入答案,然后路径向外拓展,有两种情况,一种是加入$v$出边中最小的边,第二种是加入这条边的下一条边

然后输出答案即可

正确性:

对于这样的拓展方式,考虑错误的情况,如果存在一条路径比当前堆顶更优而没有加入堆中,这种情况不可能存在,因为这条路径可以由比他更优的路径拓展而来,如果这条路径没有被加入堆中,那么也就说明他的前继路径存在于堆中没有被选中,不合法,所以贪心策略正确。

技术图片
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e4 + 5;
int n, m, Q;
ll ans[maxn];
vector<pair<int, int> > G[maxn];
struct data 
    ll w;
    int u, v, p;
    data() 
    data(ll _w, int _u, int _v, int _p) : w(_w), u(_u), v(_v), p(_p) 
    bool friend operator < (const data &a, const data &b) 
        return a.w > b.w;
    
;
int main() 
    int T; scanf("%d", &T);
    while(T--) 
        scanf("%d%d%d", &n, &m, &Q);
        memset(ans, 0, sizeof(ans));
        for(int i = 1; i <= n; ++i) G[i].clear();
        priority_queue<data> q;
        for(int i = 1; i <= m; ++i) 
            int u, v, w; scanf("%d%d%d", &u, &v, &w);
            G[u].push_back(make_pair(w, v));
         
        for(int i = 1; i <= n; ++i) sort(G[i].begin(), G[i].end());
        for(int i = 1; i <= n; ++i) if(!G[i].empty()) q.push(data(G[i][0].first, i, G[i][0].second, 0));
        for(int _ = 1; _ <= 50000 && !q.empty(); ++_) 
            data t = q.top();
            q.pop();
            ans[_] = t.w;
            int u = t.u, v = t.v, p = t.p;
            if(G[v].size()) q.push(data(t.w + G[v][0].first, v, G[v][0].second, 0));
            if(p != (int)G[u].size() - 1) q.push(data(t.w + G[u][p + 1].first - G[u][p].first, u, G[u][p + 1].second, p + 1));
        
        while(Q--) 
            int k; scanf("%d", &k);
            printf("%lld\n", ans[k]);
        
    
    return 0;
 
View Code

 

以上是关于hdu 6705的主要内容,如果未能解决你的问题,请参考以下文章

2019ccpc缃戠粶璧沨du6705 path

ccpc20190823

2019 CCPC - 网络选拔赛 D path(求第k短路)

BetaFlight模块设计之十八:图传模块同步任务分析

java 正则表达式语法

从管道分隔文件中获取值