zoukankan      html  css  js  c++  java
  • 分层图学习笔记 & [JLOI2011]飞行路线题解

    分层图实际上就是把一个图复制好几份,分别代表每一层图,相邻的层之间的节点如果在原图有边就可以连边,同一层节点之间在原图有边也连边。

    这里蓝边就是相邻层的边,黑边就是同一层之间的边。原图就是 ((1,2),(1,3)) 两条边。

    Luogu P4568 [JLOI2011]飞行路线

    给定一个图,每个图之间有边权,可以将 (k) 个边的边权改为 (0) ,求 (S)(T) 的最短路。

    其中 (2leq nleq 10^4,1leq mleq 5 imes 10^4,0leq kleq 10)

    可以把这个图分成 (k) 层的分层图,那么现在每个点和每条边代表什么意思呢?定义在第 (i) 层的节点为用了 (i) 次边权取 (0) 的节点,那么每个黑边在同一层图内走代表的就是没有使用边权取 (0), 而走蓝边就是代表把边权取 (0),然后走到下一层图(也就是代表使用了一次边权取 (0) 的操作)。

    这个时候以第 (0) 层图的 (s) 为起点跑最短路,答案为每一层 (t) 的最短路的最小值。

    (mathcal{Code})

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define pp  std::pair<int, int> 
    #define mp  std::make_pair 
    #define fir first
    #define sec second
    const int N = 10010;
    const int M = 50010;
    const int K = 21;
    const int INF = 0x7fffffff;
    inline int Min(int x, int y) { return x < y ? x : y; }
    inline int read() {
    	int r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-') w = 1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		r = (r << 3) + (r << 1) + (ch ^ 48);
    		ch = getchar();
    	}
    	return w ? ~r + 1 : r;
    }
    int n, m, k, s, t, ans = INF;
    int dis[N * K];
    bool vis[N * K];
    //Edge
    int head[N * K], ent;
    struct Node {
    	int next, to, val;
    }e[2 * ((2 + K) * M + K)];
    inline void add(int x, int y, int z) {
    	e[++ent].to = y; e[ent].val = z; e[ent].next = head[x]; head[x] = ent;
    }
    std::priority_queue<pp>q;
    void Dij() {
    	dis[s] = 0;
    	q.push(mp(-dis[s], s));
    	while(!q.empty()) {
    		int x = q.top().sec;
    		q.pop();
    		if(vis[x]) continue;
    		vis[x] = 1;
    		for(int i = head[x] ; i; i = e[i].next) {
    			int v = e[i].to;
    			if(dis[v] > dis[x] + e[i].val) {
    				dis[v] = dis[x] + e[i].val;
    				if(!vis[v]) q.push(mp(-dis[v], v));
    			}
    		}
    	}
    }
    signed main() {
    	n = read(); m = read(); k = read(); s = read(); t = read();
    	for(int i = 1; i <= m; ++i) {
    		int x = read(), y = read(), z = read();
    		add(x, y, z); add(y, x, z);
    		for(int j = 1; j <= k; ++j) {
    			add(x + (j - 1) * n, y + j * n, 0);
    			add(y + (j - 1) * n, x + j * n, 0);
    			add(x + j * n, y + j * n, z);
    			add(y + j * n, x + j * n, z);
    		}
    	}
    	for(int i = 0; i < n; ++i)
    		for(int j = 0; j <= k; ++j)
    			dis[i + j * n] = INF;
    	Dij();
    	for(int i = 0; i <= k; ++i) ans = Min(ans, dis[t + i * n]);
    	printf("%d
    ", ans);
    	return 0;
    }
    

    练习题目:

    Luogu P2939[USACO09FEB]Revamping Trails G

    Luogu P4822 [BJWC2012]冻结

    Luogu P4822 [BJWC2012]冻结 参考代码

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define pp  std::pair<int, int>
    #define mp  std::make_pair
    #define frist fsr
    #define sec second
    const int N = 501000;
    int n, m, k;
    inline int Min(int x, int y) { return x < y ? x : y; }
    inline int read() {
    	int r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-') w = 1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		r = (r << 3) + (r << 1) + (ch ^ 48);
    		ch = getchar();
    	}
    	return w ? ~r + 1 : r;
    }
    int head[N], ent, dis[N];
    bool vis[N];
    struct Node {
    	int next, to, val;
    }e[N << 1];
    inline void add(int x, int y, int z) {
    	e[++ent].to = y; e[ent].next = head[x]; e[ent].val = z; head[x] = ent;
    }
    std::priority_queue<pp>q;
    signed main() {
    	n = read(); m = read(); k = read();
    	for(int i = 1; i <= m; ++i) {
    		int x = read(), y = read(), z = read();
    		add(x, y, z); add(y, x, z);
    		for(int j = 1; j <= k; ++j) {
    			add(x + j * n, y + j * n, z);
    			add(y + j * n, x + j * n, z);
    			add(x + (j - 1) * n, y + j * n, z / 2);
    			add(y + (j - 1) * n, x + j * n, z / 2);
    		}
    	}
    	for(int i = 1; i <= n; ++i)
    		for(int j = 0; j <= k; ++j)
    			dis[i + j * n] = 0x7fffffff;
    	dis[1] = 0;
    	q.push(mp(0,1));
    	while(!q.empty()) {
    		int x = q.top().sec;q.pop();
    		if(vis[x]) continue;
    		vis[x] = 1;
    		for(int i = head[x]; i; i = e[i].next) {
    			int v = e[i].to;
    			if(dis[v] > dis[x] + e[i].val) {
    				dis[v] = dis[x] + e[i].val;
    				if(!vis[v])
    					q.push(mp(-dis[v], v));
    			}
    		}
    	}
    	int ans = 0x7fffffff;
    	for(int i = 0; i <= k; ++i)
    		ans = Min(ans, dis[i * n + n]);
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    UIWebvView 解决onClick 延迟相应问题
    MySQL 5.6.x 配置数据库主从复制
    SDWebImage 常用方法
    OSX/iOS 播放系统声音
    UIView 设置阴影(属性说明)
    Response的Content-Type一览
    Linux查看端口占用情况并释放端口占用
    Windows安装配置Anaconda2/PyCharm
    bui框架nav导航图标一览
    服务器验证码乱码问题记录(字体库添加)
  • 原文地址:https://www.cnblogs.com/do-while-true/p/13772996.html
Copyright © 2011-2022 走看看