• 【YBTOJ】【Luogu P1073】[NOIP2009 提高组] 最优贸易


    链接:

    洛谷

    题目大意:

    在一个有向图上找到一个二元组 ((u,v)) 满足有一条 (1 o u o v o n) 的路径,并且 (Val(v)-Val(u)) 最大。

    正文:

    (Val(v)-Val(u)) 最大,相当于 (Val(u)) 尽量小且 (Val(v)) 尽量大。

    再把路径拆成 (1 o u, v o n) 分别考虑:

    • 第一条路径直接求最短路(边权即点权)。

    • 第二条路径反图求最长路(从 (n) 点出发)。

    然后枚举路径 (u o v) 的中介点 (i),接下来就是找最大的 ( ext{dist}_{v o n}(i)- ext{dist}_{1 o u}(i)),这里的下标就是上文的最短路和最长路。

    代码:

    const int N = 1e5 + 10, M = 1e6 + 10;
    
    inline ll Read()
    {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = -f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
    	return x * f;
    }
    
    int n, m;
    int a[N];
    
    struct edge
    {
    	int to, nxt, val;
    }e[2][M];
    int head[2][N], tot[2];
    void Add(int u, int v, int w, bool I)
    {
    	e[I][++tot[I]] = (edge) {v, head[I][u], w}, head[I][u] = tot[I];
    }
    
    int dis[2][N];
    bool vis[2][N];
    queue <int> q;
    
    int com(bool I, int a, int b) 
    {
    	return !I? min(a, b) : max(a, b);
    } 
    
    int Com(bool I, int a, int b) 
    {
    	return !I? a < b : a > b;
    } 
    
    void SPFA(int s, bool I)
    {
    	while(!q.empty()) q.pop();
    	dis[I][s] = a[s];
    	vis[I][s] = 1;
    	q.push(s);
    	while (!q.empty())
    	{
    		int u = q.front(); q.pop();
    		for (int i = head[I][u], v; i; i = e[I][i].nxt)
    			if(Com(I, com(I, dis[I][u], e[I][i].val), dis[I][v = e[I][i].to]))
    			{
    				dis[I][v] = com(I, dis[I][u], e[I][i].val);
    				if (vis[I][v]) continue;
    				vis[I][v] = 1;
    				q.push(v);
    			}
    		vis[I][u] = 0;
    	}
    }
    
    void Solve()
    {
    	memset (dis[0], 127 / 3, sizeof dis[0]);
    	memset (dis[1], 0, sizeof dis[1]);
    	memset (vis, 0, sizeof vis);
    	SPFA(1, 0), SPFA(n, 1);
    	int ans = 0;
    	for (int i = 1; i <= n; i++)
    		ans = max(ans, dis[1][i] - dis[0][i]);
    	printf ("%d
    ", ans);
    	return;
    }
    
    int main()
    {
    	n = Read(), m = Read();
    	for (int i = 1; i <= n; i++) a[i] = Read();
    	for (int i = 1; i <= m; i++)
    	{
    		int u = Read(), v = Read(), opt = Read();
    		Add(u, v, a[v], 0), Add(v, u, a[v], 1);
    		if (opt - 1) Add(v, u, a[u], 0), Add(u, v, a[u], 1);
    	}
    	Solve();
    	return 0;
    }
    
    
  • 相关阅读:
    IOS10.8.2安装
    如何读本地资源图片
    SqlServer2000日志文件过大问题处理
    xcode 4.5.1 免证书开发 破解
    C#生成注册码
    去掉Html标签方法
    数组处理
    返回代码
    Javascript图像处理——图像金字塔
    Javascript图像处理——图像形态学
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14790762.html
Copyright © 2020-2023  润新知