【luogu P2939 [USACO09FEB]改造路Revamping Trails】 题解

题目链接:https://www.luogu.org/problemnew/show/P2939
本来说是双倍经验题,跟飞行路线一样的,结果我飞行路线拿deque优化SPFA过了这里过不了了。
所以多学一种优先队列优化。

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
const ll maxn = 200000 + 10;
const ll inf = 2147483647;
inline ll read()
{
    ll k=0,f=1;
    char c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(isdigit(c))
    {
        k=(k<<1)+(k<<3)+c-48;
        c=getchar();
    }
    return k*f;
}
ll n, m, k, s, end, dis[maxn][30];
bool vis[maxn][30];
struct edge{
    ll from, len, to, next;
}e[maxn<<2];
ll head[maxn], cnt = 0;
struct que{
    ll a, b;
};
struct cmp{
    bool operator ()(que &x, que &y)
    {
        return dis[x.a][x.b] > dis[y.a][y.b];
    }
};
priority_queue<que, vector<que>, cmp> q;
void add(ll u, ll v, ll w)
{
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].len = w;
    e[cnt].next = head[u];
    head[u] = cnt;
}
void SPFA()
{
    memset(dis, 127, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    q.push((que){s,0});
    dis[s][0] = 0;
    vis[s][0] = 1;
    while(!q.empty())
    {
        que now = q.top(); q.pop();
        vis[now.a][now.b] = 0;
        for(ll i = head[now.a]; i != -1; i = e[i].next)
        {
            if(dis[e[i].to][now.b] > dis[now.a][now.b] + e[i].len)
            {
               dis[e[i].to][now.b] = dis[now.a][now.b] + e[i].len;
               if(vis[e[i].to][now.b] == 0)
               {
                  vis[e[i].to][now.b] = 1;
                  q.push((que){e[i].to, now.b});
                    }
            }
            if(now.b + 1 <= k)
            {
                if(dis[e[i].to][now.b + 1] > dis[now.a][now.b])
                {
                    dis[e[i].to][now.b + 1] = dis[now.a][now.b];
                    if(vis[e[i].to][now.b + 1] == 0)
                    {
                        vis[e[i].to][now.b + 1] = 1;
                        q.push((que){e[i].to, now.b + 1});
                    }
                }
            }
        }
    }
}
int main()
{
    memset(head, -1, sizeof(head));
    n = read(); m = read(); k = read();
    s = 1, end = n;
    for(ll i = 1; i <= m; i++)
    {
        ll u, v, w;
        u = read(); v = read(); w = read();
        add(u, v, w); add(v, u, w);
    }
    SPFA();
    printf("%lld",dis[end][k]);
    return 0;
}

原文地址:https://www.cnblogs.com/MisakaAzusa/p/9332180.html

时间: 2024-10-10 19:02:00

【luogu P2939 [USACO09FEB]改造路Revamping Trails】 题解的相关文章

P2939 [USACO09FEB]改造路Revamping Trails

传送门 显然的分层图 设 dis [ i ] [ j ] 表示到点 i , 已经建立了 j 条高速公路的最短距离 然后转移每次都分建立高速公路和不建立高速公路两种情况 跑Djikstra #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std

【分层图最短路,dijstra】P2939 [USACO09FEB]改造路Revamping Trails

1 #include<iostream> 2 #include<string> 3 #include<queue> 4 #include<stack> 5 #include<vector> 6 #include<map> 7 #include<cstdio> 8 #include<cstdlib> 9 #include<algorithm> 10 #include<set> 11 #in

[USACO09FEB]改造路Revamping Trails

题目描述 Farmer John dutifully checks on the cows every day. He traverses some of the M (1 <= M <= 50,000) trails conveniently numbered 1..M from pasture 1 all the way out to pasture N (a journey which is always possible for trail maps given in the test

luoguP2939 [USACO09FEB]改造路Revamping Trails

约翰一共有N)个牧场.由M条布满尘埃的小径连接.小径可 以双向通行.每天早上约翰从牧场1出发到牧场N去给奶牛检查身体. 通过每条小径都需要消耗一定的时间.约翰打算升级其中K条小径,使之成为高 速公路.在高速公路上的通行几乎是瞬间完成的,所以高速公路的通行时间为0. 请帮助约翰决定对哪些小径进行升级,使他每天早上到牧场W花的时间最少.输出这个最少 的时间. 分层图DP,启发良多 1.远离SPFA,Dijstra+堆稳定多了 2.要在Dijstra中Dp,堆中必须包含三要素:当前点.层数.距离,缺一

USACO09FEB 改造路Revamping Trails(分层图模板)

满分做法: 因为\(k\)很小,所以把每个点拆出\(k\)个点,对应使了多少个高速,这个就是分层图了. #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<cmath> using namespace std; typedef long long ll; const int maxm=300

【USACO09FEB】改造路Revamping Trails

链接 显而易见的 dp 方程,dp [ x ] [ i ] 表示到达点 x 免费了 i 条边的最短时间. dp [ x ] [ i ] = min ( dp [ pre ] [ i - 1 ] , dp [ pre ] [ i ] + dis [ pre ] [ x ] ) ; 如果直接跑dp,得搞个拓扑图,并且环上信息不会统计. 考虑分层图,然后就是一个分层图模板了. (回家画个图) 1 #include<cstdio> 2 #include<string> 3 #include

P2939 [USACO09FEB]改造路[分层图最短路]

题意翻译 约翰一共有N)个牧场.由M条布满尘埃的小径连接.小径可 以双向通行.每天早上约翰从牧场1出发到牧场N去给奶牛检查身体. 通过每条小径都需要消耗一定的时间.约翰打算升级其中K条小径,使之成为高 速公路.在高速公路上的通行几乎是瞬间完成的,所以高速公路的通行时间为0. 请帮助约翰决定对哪些小径进行升级,使他每天从1号牧场到第N号牧场所花的时间最短 解析 提高练习场看到这题,瞄一眼,诶,这不是分层图裸题吗??? [啥是分层图] 分层图,简单来说,就是把一张图复制多次,分为多份,每层图代表一种

Bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 dijkstra,堆,分层图

1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1573  Solved: 428[Submit][Status][Discuss] Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N;

BZOJ 1579: [Usaco2009 Feb]Revamping Trails 道路升级( 最短路 )

最短路...多加一维表示更新了多少条路 ---------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<iostream> #define rep( i , n ) for( int i