path hdu6705

题意:

一个有向加权图,问所有路径汇中第k小的路径长度是多少?
注意一个边可以反复走多次

题解

做法参考
我们可以利用优先队列来做
利用优先队列实现每次所取为最短边
我们假设一条路是从u—>v,路径和为sum,u->v是u的所以出边中边权第cur小的边,那么我们接下来有两种方案可以走:
第一种:就是接着从v走下去,从v继续走到v->w,(w为距离v最近的点,w!=u),cur为0,因为w是v第(cur+1)小的选择,也就是g[v][0]=w
此时sum+g[v][0]
第二种:
我认为这一步算是返回的步骤
就是继续从u出发,走u下一个边权较大于v的点,因为v是第cur小的选项,所以此等方案为cur+1
sum-g[u][cur].w+g[u][cur+1].w
我们的sum是记录了u到v的边权,所以先去掉,再加上新边权

代码中的cur是用来距离v是u的第几小的选择,
我们全程不断计算新的路径情况,并将路径长度存到优先队列q中,不断排序

代码

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=5e5+50;
int n,m,q;
LL ans[maxn];
struct edge
{
   
    int to;
    LL w;
};
vector<edge> g[maxn];
bool cmp(const edge &x,const edge &y)
{
   
    return x.w<y.w;
}
struct node
{
   
    int u,v;
    int cur;
    LL sum;
    friend bool operator < (const node &x,const node &y)
    {
   
        return x.sum>y.sum;
    }
};
void init()
{
   
    for(int i=1;i<=n;i++)
        g[i].clear();
}
void solve()
{
   
    for(int i=1;i<=n;i++)
        sort(g[i].begin(),g[i].end(),cmp);
    priority_queue<node> q;
    for(int i=1;i<=n;i++)
    {
   
        if(!g[i].empty())
            q.push(node{
   i,g[i][0].to,0,g[i][0].w});
    }
    for(int i=1;i<=50000;i++)
    {
   
        int u=q.top().u,v=q.top().v,cur=q.top().cur;
        LL sum=q.top().sum;
        q.pop();
        ans[i]=sum;
        if(!g[v].empty())
            q.push(node{
   v,g[v][0].to,0,sum+g[v][0].w});
        if(cur+1<g[u].size())
            q.push(node{
   u,g[u][cur+1].to,cur+1,sum-g[u][cur].w+g[u][cur+1].w});
    }
}
int main()
{
   
    int T;
    scanf("%d",&T);
    while(T--)
    {
   
        scanf("%d %d %d",&n,&m,&q);
        init();
        for(int i=1;i<=m;i++)
        {
   
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            g[u].push_back(edge{
   v,w});
        }
        solve();
        while(q--)
        {
   
            int k;
            scanf("%d",&k);
            printf("%lld\n",ans[k]);
        }
    }
    return 0;
}


全部评论

相关推荐

12-14 11:43
黑龙江大学 Java
用微笑面对困难:确实比较烂,可以这么修改:加上大学的qs排名,然后大学简介要写一些,然后硕士大学加大加粗,科研经历第一句话都写上在复旦大学时,主要负责xxxx,简历左上角把学校logo写上,建议用复旦大学的简历模板
点赞 评论 收藏
分享
程序员花海:1.技能放最后,来面试默认你都会,技能没啥用 2.实习写的看起来没啥含金量,多读读部门文档,包装下 接LLM这个没含金量 也不要用重构这种 不会给实习生做的 3.抽奖这个还是Demo项目,实际在公司里面要考虑策略,满减,触发点,触发规则 库存 之类的,不是这个项目这么简单 4.教育背景提前,格式为 教育背景 实习 项目 技能 自我评价
简历被挂麻了,求建议
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务