ccpc网赛 hdu6705 path(队列模拟 贪心

http://acm.hdu.edu.cn/showproblem.php?pid=6705

这是比赛前8题过的人数第二少的题,于是就来补了,但感觉并不难啊。。(怕不是签到难度

题意:给个图,给几条路,让你求第k短路,所有路径不限制使用次数。

思路:最短路肯定是最短的那条,第2短就有2种可能,可能是长度第二短的那条,也有可能是接着刚才的最短路继续走(2个还不会,但是先这样拓展),到第3短就真的是2种可能了(例如1,2,9,1+2<9),但是k短路显然最多是由k段拼成(反证法:如果是k+1条,那个把第k+1段扔了就会更小,所以肯定不是最优),所以直接循环max(k)次,第i次循环就把i段拼成的路更新进去就行。可以开优先队列,装路径总长和终点的struct。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e4+10;
struct node{
    ll to,len;
    node(){}
    node(ll a,ll b):to(a),len(b){}
};
struct cmp{
    bool operator ()(const node &x,const node &y) const{
        return x.len>y.len;
    }
};
bool cmp1(node a,node b){
    return a.len<b.len;
}
priority_queue<node,vector<node>,cmp > q0;
priority_queue<int> q1;
vector<node> ve[N];
ll a[N],b[N];
void init(int n){
    while(!q1.empty()) q1.pop();
    while(!q0.empty()) q0.pop();
    for(int i=1;i<=n;i++) ve[i].clear();
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    ll t;
    cin>>t;
    while(t--){
        ll n,m,k;
        cin>>n>>m>>k;
        init(n);
        for(ll i=1;i<=m;i++){
            ll u,v,w;
            cin>>u>>v>>w;
            q0.push({v,w});
            q1.push(w);
            ve[u].push_back(node(v,w));
        }
        for(ll i=1;i<=n;i++){
            sort(ve[i].begin(),ve[i].end(),cmp1);
        }
        ll mx = 0;
        for(ll i=0;i<k;i++){
            cin>>a[i];
            mx = max(mx,a[i]);
        }
        for(ll i=1;i<=mx;i++){
            b[i] = q0.top().len;
            ll x = q0.top().to;
            q0.pop();
            for(int j=0;j<ve[x].size();j++){
                ll y=ve[x][j].to,len=b[i]+ve[x][j].len;
                if(q1.size()==mx){
                    if(len>q1.top()) break;
                    else{
                        q1.pop();
                        q1.push(len);
                        q0.push({y,len});
                    }
                }
                else {
                    q1.push(len);
                    q0.push({y,len});
                }
            }
        }
        for(ll i=0;i<k;i++) cout<<b[a[i]]<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wzgg/p/11410161.html