【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;
}

posted @ 2018-07-18 19:29  Misaka_Azusa  阅读(154)  评论(0编辑  收藏  举报
Live2D