zoukankan      html  css  js  c++  java
  • 分层图学习笔记

    分层图

    重要性质

    1. 可以理解为有多个平行的图。
    2. 上一层不能到达下一层,但下一层能到达上一层。

    分层图最短路

    一般模型

    在一个正常的图上可以进行 k次决策,对于每次决策,不影响图的结构,只影响目前的状态或代价。一般将决策前的状态和决策后的状态之间连接一条权值为决策代价的边,表示付出该代价后就可以转换状态了。

    两种解法

    1. 建图时直接建成k+1层。
    2. 多开一维记录机会信息。
      (视数据范围而定)

    Luogu-P4568飞行路线

    解法

    不就是最短路减前k大的边
    分层图模板
    正经的dijstra

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define lson x<<1
    #define rson x<<1|1
    #define ll long long
    #define rint register int
    #define mid  ((L + R) >> 1)
    using namespace std;
    template <typename xxx> inline void read(xxx &x) {
    	char c = getchar(),f = 1;x = 0;
    	for(;c ^ '-' && !isdigit(c);c = getchar());
    	if(c == '-') c = getchar(),f = -1;
    	for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
    	x *= f;
    }
    template<typename xxx>void print(xxx x)
    {
        if(x<0){putchar('-');x=-x;}
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    const int maxn = 1010010;
    const int inf = 0x7fffffff;
    const int mod = 1e9 + 7;
    struct edge{
    	int to,last,val;
    }e[maxn<<1];
    int tot,head[maxn];
    inline void add(int from,int to,int val) {
    	++tot;
    	e[tot].to = to;
    	e[tot].val = val;
    	e[tot].last = head[from];
    	head[from] = tot;
    }
    int dis[maxn][12];
    int vis[maxn][12];
    int n,m,K;
    int s,t;
    struct node {
    	int pla,cos,kkk;
    	bool operator < (const node & x) const {
    		return cos > x.cos;
    	}
    };
    priority_queue< node >q;
    inline void dj() {
    	for(rint i = 0;i <= n; ++i) {
    		for(rint j = 0;j <= K; ++j) {
    			dis[i][j] = inf;
    			vis[i][j] = 0;
    		}
    	}
    	q.push((node){s,0,0});dis[s][0] = 0;
    	while(q.size()) {
    		node x = q.top();
    		q.pop();
    		if(vis[x.pla][x.kkk]) continue;
    		vis[x.pla][x.kkk] = 1;
    		for(rint i = head[x.pla]; i; i = e[i].last) {
    			if(dis[e[i].to][x.kkk] > dis[x.pla][x.kkk] + e[i].val) {
    				dis[e[i].to][x.kkk] = dis[x.pla][x.kkk] + e[i].val;
    				q.push((node){e[i].to,dis[e[i].to][x.kkk],x.kkk});
    			}
    			if(x.kkk < K) {
    				if(dis[e[i].to][x.kkk + 1] > dis[x.pla][x.kkk]) {
    					dis[e[i].to][x.kkk + 1] = dis[x.pla][x.kkk];
    					q.push((node){e[i].to,dis[e[i].to][x.kkk + 1],x.kkk + 1});
    				}
    			}
    		}
    	} 
    	return ;
    }
    int main()
    {
    	read(n);read(m);read(K);
    	read(s);read(t);++s,++t;
    	for(rint i = 1;i <= m; ++i) {
    		int a,b,c;
    		read(a);read(b);read(c);
    		++a,++b;
    		add(a,b,c);add(b,a,c);	
    	}
    	dj();
    	int ans = inf;
    	for(rint i = 0;i <= K; ++i) {
    		if(ans > dis[t][i]) ans = dis[t][i];
    	}
    	print(ans);
    	return 0;
    }
    /*
    5 6 
    0 4
    0 1 5
    1 2 5
    2 3 5
    3 4 5
    2 3 3
    0 2 100
    */
    /*
    */
    

    又被卡死的spfa

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define lson x<<1
    #define rson x<<1|1
    #define ll long long
    #define rint register int
    #define mid  ((L + R) >> 1)
    using namespace std;
    template <typename xxx> inline void read(xxx &x) {
    	char c = getchar(),f = 1;x = 0;
    	for(;c ^ '-' && !isdigit(c);c = getchar());
    	if(c == '-') c = getchar(),f = -1;
    	for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
    	x *= f;
    }
    template<typename xxx>void print(xxx x)
    {
        if(x<0){putchar('-');x=-x;}
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    const int maxn = 1000110;
    const int inf = 0x7fffffff;
    const int mod = 1e9 + 7;
    struct edge{
    	int to,last,val;
    }e[maxn<<1];
    int tot,head[maxn];
    inline void add(int from,int to,int val) {
    	++tot;
    	e[tot].to = to;
    	e[tot].val = val;
    	e[tot].last = head[from];
    	head[from] = tot;
    }
    int dis[maxn][12];
    int vis[maxn][12];
    int n,m,K;
    int s,t;
    queue< pair<int,int> >q;
    inline void spfa() {
    	for(rint i = 0;i <= n; ++i) {
    		for(rint j = 0;j <= K; ++j) {
    			dis[i][j] = inf;
    			vis[i][j] = 0;
    		}
    	}
    	q.push(make_pair(s,0));dis[s][0] = 0;
    	while(q.size()) {
    		int x = q.front().first;
    		int y = q.front().second;
    		q.pop();vis[x][y] = 0;
    		for(rint i = head[x]; i; i = e[i].last) {
    			if(dis[e[i].to][y] > dis[x][y] + e[i].val) {
    				dis[e[i].to][y] = dis[x][y] + e[i].val;
    				if(!vis[e[i].to][y]) {
    					vis[e[i].to][y] = 1;
    					q.push(make_pair(e[i].to,y));
    				}
    			}
    			if(y < K) {
    				if(dis[e[i].to][y + 1] > dis[x][y]) {
    					dis[e[i].to][y + 1] = dis[x][y];
    					if(!vis[e[i].to][y + 1]) {
    						vis[e[i].to][y + 1] = 1;
    						q.push(make_pair(e[i].to,y + 1));
    					}
    				}
    			}
    		}
    	} 
    	return ;
    }
    int main()
    {
    	read(n);read(m);read(K);
    	read(s);read(t);++s,++t;
    	for(rint i = 1;i <= m; ++i) {
    		int a,b,c;
    		read(a);read(b);read(c);
    		++a,++b;
    		add(a,b,c);add(b,a,c);	
    	}
    	spfa();
    	int ans = inf;
    	for(rint i = 0;i <= K; ++i) {
    		if(ans > dis[t][i]) ans = dis[t][i];
    	}
    	print(ans);
    	return 0;
    }
    /*
    */
    

    推荐博客

  • 相关阅读:
    简单的描述关于开发部署产生401,500的错误处理
    文件的批量打包下载
    json的序列化与反序列化
    实现MD5的加密和解密
    dropdownlist的OnSelectedIndexChanged方法不触发
    sqlserver错误2,error 40
    C#存储过程调用的三个方法
    SQL Server 错误:924 解决方法
    判断是否在时间间隔内
    切面添加日志
  • 原文地址:https://www.cnblogs.com/Thomastine/p/11812411.html
Copyright © 2011-2022 走看看