zoukankan      html  css  js  c++  java
  • P1073 最优贸易 DFS

    题目传送门

    cnblog宣传

    题意:(n)个城市,(m)条边(单向或双向)

       每个城市对于水晶球有一个价格(买的价格与卖的价格相等)

       现在从(1)走到(n),可重复经过城市,

       问能赚到的最大差价(在最小的地方买,最大的地方卖,且只进行一次买卖)

       输入边(a, b, c)表示a到b有((c=1) 单向 (c=2)双向)​边

    题解:

    在这里提供一种只用到DFS的算法

    题目可以转化为在图中找两个点权差值最大的点

    这两个点要保证从(1)(n)遍历时先遍历到点权小的点,再遍历到点权大的点。

    (maxl[i])代表从i到终点能到的最大的点

    (minl[i])代表从起点到i能走到的最小的点

    正向建图DFS求(minl)

    反向建图DFS求(maxl)

    最后(ans = max^n_{i=1}(maxl[i]-minl[i]))

    注:在建图时,采用的是一种比较特别的方式。

    将所有的边建成双向边。

    其中给不同的边附上不同的权值。

    正向边边权附(1),反向边边权附(2)

    双向边边权附(3)

    在DFS时进行判断次边是否可走即可

    code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N = 1e5 + 5, M = 5e5 + 5;
    int ans, z, n, m, cnt;
    int head[N], to[M], nxt[M], maxl[N], minl[N], vis[N], tag[M];
    void add(int u, int v, int t) {
    	to[++ cnt] = v;
    	tag[cnt] = t;
    	nxt[cnt] = head[u];
    	head[u] = cnt;
    }
    void dfs1(int x, int v) {
    	if(vis[x] == 1) return;
    	vis[x] = 1;
    	minl[x] = min(minl[x], v);
    	for(int i = head[x]; i ;i = nxt[i]) {
    		int v = to[i];
    		if(vis[v] == 1||tag[i] == 2) continue;
    		dfs1(v, minl[x]);
    	}
    }
    void dfs2(int x, int v) {
    	if(vis[x] == 1) return;
    	vis[x] = 1;
    	maxl[x] = max(maxl[x], v);
    	for(int i = head[x]; i ;i = nxt[i]) {
    		int v = to[i];
    		if(vis[v] == 1 || tag[i] == 1) continue;
    		dfs2(v, maxl[x]);
    	}
    	ans = max(ans, maxl[x] - minl[x]);
    }
    int main() {
    	cin >> n >> m;
    	for(int i = 1;i <= n;i ++) cin >> minl[i], maxl[i] = minl[i];
    	for(int i = 1, x, y;i <= m;i ++) {
    		cin >> x >> y >> z;
    		if(z == 1) add(x, y, 1), add(y, x, 2);
    		if(z == 2) add(x, y, 3), add(y, x, 3);
    	}
    	dfs1(1, minl[1]);
    	memset(vis, 0, sizeof(vis));
    	dfs2(n, maxl[n]);
    	cout << ans << endl;
    	return 0;
    } 
    
  • 相关阅读:
    微信小程序开发---各代码文件简介
    LeetCode71. 简化路径
    LeetCode70. 爬楼梯
    LeetCode69. x 的平方根
    LeetCode68. 文本左右对齐
    LeetCode剑指 Offer 09. 用两个栈实现队列
    LeetCode67. 二进制求和
    LeetCode66. 加一
    LeetCode65. 有效数字
    LeetCode64. 最小路径和
  • 原文地址:https://www.cnblogs.com/Paranoid-LS/p/11502622.html
Copyright © 2011-2022 走看看