• 分层图学习笔记 & [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;
    }
    
  • 相关阅读:
    进程与线程
    the art of seo(chapter seven)
    the art of seo(chapter six)
    the art of seo(chapter five)
    the art of seo(chapter four)
    the art of seo(chapter three)
    the art of seo(chapter two)
    the art of seo(chapter one)
    Sentinel Cluster流程分析
    Sentinel Core流程分析
  • 原文地址:https://www.cnblogs.com/do-while-true/p/13772996.html
Copyright © 2020-2023  润新知