分层图求最短路学习笔记

单纯的最短路和网络流 大家都会
但是如果增加了点干扰物 可能就停滞在前了
如选择一些路使其权值为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] d i s [ i ] [ k ] 表示走到第 i i 号点 ,免费经过了 k k 条边的最短路.
对于当前每条边 我们讨论使其免费和不免费两种状态 并更新当前最短路 压入队列 参与之后的更新

改造路’s Code C o d e

#include 
#include 
#include 
#include 
#include 
#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  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 C o d e

#include 
#include 
#include 
#include 
#include 
#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  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;
}

你可能感兴趣的:(分层图)