1. 程式人生 > >分層圖求最短路學習筆記

分層圖求最短路學習筆記

單純的最短路和網路流 大家都會
但是如果增加了點干擾物 可能就停滯在前了

例題

我們設定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;
}