• 计蒜客 31001


    题目链接:https://nanti.jisuanke.com/t/31001

    题意:

    一带权有向图,有 n 个节点编号1~n,m条有向边,现在一人从节点 1 出发,他有最多 k 次机会施展魔法使得某一条边的权变成 0,问他走到节点 n 的最小权值为多少。

    题解:

    将dist数组和vis数组都扩展一维:

    dist[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离;

    vis[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离,这个最短距离是否已经被准确计算完毕。

    然后就是稍微改动一下原来的优先队列优化Dijkstra即可。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn=1e5+10;
    const int maxm=2e5+10;
    const int maxk=13;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    
    int n,m,k;
    
    struct Edge{
        int u,v;
        ll w;
        Edge(int u=0,int v=0,ll w=0){this->u=u,this->v=v,this->w=w;}
    };
    vector<Edge> E;
    vector<int> G[maxn];
    void init(int l,int r)
    {
        E.clear();
        for(int i=l;i<=r;i++) G[i].clear();
    }
    void addedge(int u,int v,ll w)
    {
        E.push_back(Edge(u,v,w));
        G[u].push_back(E.size()-1);
    }
    
    struct Qnode{
        int vertex;
        ll dist;
        int cnt;
        Qnode(int v=0,ll d=0,int c=0){this->vertex=v,this->dist=d,this->cnt=c;}
        bool operator <(const Qnode &oth)const{
            return dist>oth.dist;
        }
        //优先队列默认是降序排列,如果本节点小于另一个节点的意义是 本节点dist < 另一个节点dist,
        //则优先队列的队首放的就是最大的节点,就是dist最大的节点,显然我们要的是相反的情况,
        //所以设置本节点小于另一个节点的意义是 本节点dist > 另一个节点dist 即可。
    };
    
    ll dist[maxk][maxn];
    bool vis[maxk][maxn];
    void dijkstra(int s)
    {
        for(int i=1;i<=n;i++)
        {
            for(int c=0;c<=k;c++)
            {
                dist[c][i]=((i==s)?0:INF);
                vis[c][i]=0;
            }
        }
    
        priority_queue<Qnode> Q;
        Q.push(Qnode(s,0,0));
        while(!Q.empty())
        {
            int u=Q.top().vertex, c=Q.top().cnt; Q.pop();
            if(vis[c][u]) continue;
            vis[c][u]=1;
            for(int i=0;i<G[u].size();i++)
            {
                Edge &e=E[G[u][i]]; int v=e.v;
                if(!vis[c][v] && dist[c][v]>dist[c][u]+e.w)
                {
                    dist[c][v]=dist[c][u]+e.w;
                    Q.push(Qnode(v,dist[c][v],c));
                }
                if(c+1<=k && !vis[c+1][v] && dist[c+1][v]>dist[c][u])
                {
                    dist[c+1][v]=dist[c][u];
                    Q.push(Qnode(v,dist[c+1][v],c+1));
                }
            }
        }
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            init(1,n);
            for(int i=1;i<=m;i++)
            {
                int u,v; ll w;
                scanf("%d%d%lld",&u,&v,&w);
                addedge(u,v,w);
            }
            dijkstra(1);
            ll ans=INF;
            for(int c=0;c<=k;c++) ans=min(ans,dist[c][n]);
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    路由重分发 最重要 最难 ccnp
    (01)Zookeeper简介
    (01)kafka以及消息系统的基本介绍
    (05)使用kafka脚本发送消息和接收消息
    (04)kafka多机多Broker(集群)的基本配置
    (03)kafka单机多Broker(伪分布式)的基本配置
    (02)安装配置kafka单Broker及其基本操作
    (02)安装zookeeper集群
    (09)使用xshell工具查看redis客户端,汉字显示乱码解决方法
    (08)redis之使用java客户端、spring连接redis、redis集群示例
  • 原文地址:https://www.cnblogs.com/dilthey/p/9594990.html
Copyright © 2020-2023  润新知