分層圖求最短路學習筆記

單純的最短路和網絡流 大家都會
但是如果增加了點干擾物 可能就停滯在前了
如選擇一些路使其權值爲0([USACO09FEB]Revamping Trails) , 選擇一些路使其權值減半([BJwc2012]凍結 )

例題

[USACO09FEB]改造路RevampingTrails |https://www.luogu.org/problemnew/show/P2939
[JLOI2011]飛行路線https://www.lydsy.com/JudgeOnline/problem.php?id=2763
[JLOI2011]飛行路線https://www.luogu.org/problemnew/show/P4568
兩個是一樣的題 只不過第一個確定了起點終點 第二個待詢問

我們設置dis[i][k] 表示走到第i 號點 ,免費經過了k 條邊的最短路.
對於當前每條邊 我們討論使其免費和不免費兩種狀態 並更新當前最短路 壓入隊列 參與之後的更新

改造路’s Code

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#define inc(i) (++ i)
#define dec(i) (-- i)
using namespace std;

const int N = 10000 + 7 , K = 20 + 2 , M = 50000 + 7;
int n , m , k , Dis[N][K];
int Head[N] , Node[M << 1] , Next[M << 1] , W[M << 1] , tot = 1;
bool inq[N][K];
struct Node_1
{
    int u , k , w;
    bool operator < (const Node_1& a)const
    {
        return w > a.w;
    }
};
priority_queue <Node_1> Q;

inline void Add(int u , int v , int w)
{
    Next[inc(tot)] = Head[u] , Head[u] = tot , W[tot] = w , Node[tot] = v;
    Next[inc(tot)] = Head[v] , Head[v] = tot , W[tot] = w , Node[tot] = u;
}

inline void Dij(int S)
{
    memset(Dis , 127 / 3 , sizeof(Dis));
    Node_1 u;
    u.u = S , u.k = 0;
    u.w = Dis[S][0] = 0 , Q.push(u) , inq[S][0] = 1;
    int v;
    while(!Q.empty())
    {
        u = Q.top() , Q.pop() , inq[u.u][u.k] = 0;
        for(int i = Head[u.u] ; i ; i = Next[i])
        {
            v = Node[i];
            if(Dis[v][u.k] > Dis[u.u][u.k] + W[i])
            {
                Dis[v][u.k] = Dis[u.u][u.k] + W[i];
                if(!inq[v][u.k]) Q.push(Node_1{v , u.k , Dis[v][u.k]}) , inq[v][u.k] = 1;
            }
            if(u.k + 1 <= k) 
                if(Dis[v][u.k + 1] > Dis[u.u][u.k])
                {
                    Dis[v][u.k + 1] = Dis[u.u][u.k];
                    if(!inq[v][u.k + 1]) Q.push(Node_1{v , u.k + 1 , Dis[v][u.k + 1]}) , inq[v][u.k + 1] = 1;
                }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m >> k;
    for(int i = 1 , u , v , w ; i <= m ; inc(i))    cin >> u >> v >> w , Add(u , v , w);
    Dij(1);
    printf("%d" , Dis[n][k]);
    return 0;
}

[JLOI2011]飛行路線’s Code

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#define inc(i) (++ i)
#define dec(i) (-- i)
using namespace std;

const int N = 10000 + 7 , K = 20 + 2 , M = 50000 + 7;
int n , m , k , Dis[N][K] , S , E;
int Head[N] , Node[M << 1] , Next[M << 1] , W[M << 1] , tot = 1;
bool inq[N][K];
struct Node_1
{
    int u , k , w;
    bool operator < (const Node_1& a)const//優先隊列套上結構體判斷語句需要打const
    {
        return w > a.w;
    }
};
priority_queue <Node_1> Q;

inline void Add(int u , int v , int w)
{
    Next[inc(tot)] = Head[u] , Head[u] = tot , W[tot] = w , Node[tot] = v;
    Next[inc(tot)] = Head[v] , Head[v] = tot , W[tot] = w , Node[tot] = u;
}

inline void Dij(int S)
{
    memset(Dis , 127 / 3 , sizeof(Dis));
    Node_1 u;
    Dis[S][0] = 0 , Q.push(Node_1{S , 0 , 0}) , inq[S][0] = 1;
    int v;
    while(!Q.empty())
    {
        u = Q.top() , Q.pop() , inq[u.u][u.k] = 0;
        for(int i = Head[u.u] ; i ; i = Next[i])
        {
            v = Node[i];
            if(Dis[v][u.k] > Dis[u.u][u.k] + W[i])
            {
                Dis[v][u.k] = Dis[u.u][u.k] + W[i];
                if(!inq[v][u.k]) Q.push(Node_1{v , u.k , Dis[v][u.k]}) , inq[v][u.k] = 1;
            }
            if(u.k + 1 <= k) 
                if(Dis[v][u.k + 1] > Dis[u.u][u.k])
                {
                    Dis[v][u.k + 1] = Dis[u.u][u.k];
                    if(!inq[v][u.k + 1]) Q.push(Node_1{v , u.k + 1 , Dis[v][u.k + 1]}) , inq[v][u.k + 1] = 1;
                }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m >> k;
    cin >> S >> E;
    for(int i = 1 , u , v , w ; i <= m ; inc(i))    cin >> u >> v >> w , Add(u + 1 , v + 1 , w);
    Dij(S + 1);
    printf("%d" , Dis[E + 1][k]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章