NOIP2009T3最优贸易(Dfs + spfa)
看到这个题,原本想先从后往前dfs,求出能到终点的点,再在这些点里从前往后spfa,用一条边上的两个城市的商品价格的差来作边权,实施过后,发现图中既有负边权,又有回路,以及各种奇奇怪怪的东西。说实话我连样例都没过,然后提交一下试试,得了10分。
然而我发现,要求赚最多钱,就是到那个点的路径上的最大价格 - 最小价格。
两边dfs——
最小价格可以从前往后搜来算。
最大价格可以从后往前搜来算。
最后枚举一边所有点maxx - minn的最大值就好。
说出来你可能不信,我是看的题解。
——代码
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream> using namespace std; int n, m, cnt1, cnt2, ans;
int a[], next1[], to1[], head1[], next2[], to2[],
head2[], maxx[], minn[]; inline void add1(int x, int y)
{
to1[cnt1] = y;
next1[cnt1] = head1[x];
head1[x] = cnt1++;
} inline void add2(int x, int y)
{
to2[cnt2] = y;
next2[cnt2] = head2[x];
head2[x] = cnt2++;
} inline void dfs2(int u, int k)
{
int i, v;
maxx[u] = max(maxx[u], k);
for(i = head2[u]; i != -; i = next2[i])
{
v = to2[i];
if(maxx[v] < k) dfs2(v, max(k, a[v]));
}
} inline void dfs1(int u, int k)
{
int i, v;
minn[u] = min(minn[u], k);
for(i = head1[u]; i != -; i = next1[i])
{
v = to1[i];
if(minn[v] > k) dfs1(v, min(k, a[v]));
}
} int main()
{
int i, j, x, y, z;
memset(head1, -, sizeof(head1));
memset(head2, -, sizeof(head2));
scanf("%d %d", &n, &m);
for(i = ; i <= n; i++)
{
scanf("%d", &a[i]);
maxx[i] = -1e9;
minn[i] = 1e9;
}
for(i = ; i <= m; i++)
{
scanf("%d %d %d", &x, &y, &z);
if(z == )
{
add1(x, y);
add1(y, x);
add2(x, y);
add2(y, x);
}
else
{
add1(x, y);
add2(y, x);
}
}
dfs1(, a[]);
dfs2(n, a[n]);
for(i = ; i <= n; i++) ans = max(ans, maxx[i] - minn[i]);
printf("%d", ans);
return ;
}
其中dfs不用设置vis来记录是否被访问过,因为有双向道路,所以走到一个点有可能会返回来,所以进行深搜的判断标准是目标点(姑且这么说吧)的最大最小值小于或大于当前点的最大最小值。这样即使走到后面的点,发现前面的点需要修改,也可以改回去。
也可以用 spfa ,改变一下松弛操作,dis 数组表示到当前点的路径上买入的最小值,最后统计一遍就行。
——代码
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream> using namespace std; const int MAXN = ;
int n, m, cnt, cnt1, ans;
int a[MAXN], head[MAXN], to[MAXN], next[MAXN], head1[MAXN], to1[MAXN], next1[MAXN], dis[MAXN];
bool b[MAXN], vis[MAXN];
queue <int> q; inline void add(int x, int y)
{
to[cnt] = y;
next[cnt] = head[x];
head[x] = cnt++;
} inline void add1(int x, int y)
{
to1[cnt1] = y;
next1[cnt1] = head1[x];
head1[x] = cnt1++;
} inline void dfs(int u)
{
int i, v;
b[u] = ;
for(i = head1[u]; i != -; i = next1[i])
{
v = to1[i];
if(!b[v]) dfs(v);
}
} inline void spfa(int u)
{
int i, v;
memset(dis, / , sizeof(dis));
q.push(u);
dis[u] = a[u];
while(!q.empty())
{
u = q.front();
q.pop();
vis[u] = ;
for(i = head[u]; i != -; i = next[i])
{
v = to[i];
if(dis[v] > min(dis[u], a[v]) && b[v])
{
dis[v] = min(dis[u], a[v]);
if(!vis[v])
{
q.push(v);
vis[v] = ;
}
}
}
}
} int main()
{
int i, j, x, y, z;
scanf("%d %d", &n, &m);
for(i = ; i <= n; i++) scanf("%d", &a[i]);
memset(head, -, sizeof(head));
memset(head1, -, sizeof(head1));
for(i = ; i <= m; i++)
{
scanf("%d %d %d", &x, &y, &z);
if(z == )
{
add(x, y);
add1(y, x);
}
else
{
add(x, y);
add(y, x);
add1(x, y);
add1(y, x);
}
}
dfs(n);
spfa();
for(i = ; i <= n; i++)
if(b[i])
ans = max(ans, a[i] - dis[i]);
printf("%d", ans);
return ;
}
NOIP2009T3最优贸易(Dfs + spfa)的更多相关文章
- NOIP2009T3最优贸易
洛谷传送门 看到这个题,原本想先从后往前dfs,求出能到终点的点,再在这些点里从前往后spfa,用一条边上的两个城市的商品价格的差来作边权,实施过后,发现图中既有负边权,又有回路,以及各种奇奇怪怪的东 ...
- 【题解】洛谷P1073 [NOIP2009TG] 最优贸易(SPFA+分层图)
次元传送门:洛谷P1073 思路 一开始看题目嗅出了强连通分量的气息 但是嫌长没打 听机房做过的dalao说可以用分层图 从来没用过 就参考题解了解一下 因为每个城市可以走好几次 所以说我们可以在图上 ...
- P1073 最优贸易 建立分层图 + spfa
P1073 最优贸易:https://www.luogu.org/problemnew/show/P1073 题意: 有n个城市,每个城市对A商品有不同的定价,问从1号城市走到n号城市可以最多赚多少差 ...
- 洛谷 P1073 最优贸易 最短路+SPFA算法
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 题面 题目链接 P1073 最优贸易 题目描述 C国有 $ n $ 个大城市和 ...
- NOIP2009 最优贸易
3. 最优贸易 (trade.pas/c/cpp) [问题描述] C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间 多只有一条道路直接相连.这 m 条道 ...
- 洛谷P1073 最优贸易 [图论,DP]
题目传送门 最优贸易 题目描述 C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这m 条道路中有一部分为单向通行的道路,一部分为双向 ...
- Codevs 1173 最优贸易 2009年NOIP全国联赛提高组
1173 最优贸易 2009年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description [问题描述] C 国有n ...
- Luogu P1073 最优贸易
题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双 ...
- 洛谷 P1073 最优贸易 解题报告
P1073 最优贸易 题目描述 \(C\)国有\(n\)个大城市和\(m\)条道路,每条道路连接这\(n\)个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这\(m\)条道路中有一部分 ...
随机推荐
- 可能是最漂亮的Spring事务管理详解 专题
微信阅读地址链接:可能是最漂亮的Spring事务管理详解 事务概念回顾 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事物的特性(ACID): 原子性: 事务是最小的执行单位,不允 ...
- Mysql多表联合更新、删除
UPDATE snyts_user u INNER JOIN snyts_order o ON u.user_id = o.user_id INNER JOIN snyts_refund_order ...
- JDK NIO SelectionKey bug
此bug项目中使用elasticSearch中出现的,原因是,nio事件选择器,在特性内核下以及jdk6版本中,出现不hold线程,死循环获取事件的bug,导致cup使用率过高: 此bug在官网已被修 ...
- Scala基础篇-05求值策略
Scala的求值策略有2种: call by value call by name 如何区分? 例子: def bar(x:Int,y: => Int) = def loop(): Int=lo ...
- 第一次提交代码到github时经常遇到的问题
最近两年在OpenStack方面做了一些工作,写了一些实验性的plugin. 本着Open Source的共享精神,想尝试提交到github,以便他人能下载使用. 当你注册完github帐号之后,点击 ...
- python的特殊数字类型(无穷大、无穷小等)
float('inf') 表示正无穷 -float('inf') 或 float('-inf') 表示负无穷 其中,inf 均可以写成 Inf 起步python中整型不用担心溢出,因为python理论 ...
- 按名字寻找文件和文件夹 find命令
find <指定目录> <指定条件> <指定动作> find /home/bnrc/py-faster-rcnn/caffe-fast-rcnn/ -name 'd ...
- 二分 || UOJ 148 跳石头
L距离中有n块石头,位置在d[i], 移走m块,使从起点0跳到终点l时,每次跳跃的最小距离最大,求这个最小距离 *解法:想到二分(想不到),对要求的结果进行二分,于是对最小距离二分== #includ ...
- treeTable的使用(ajax异步获取数据,动态渲染treeTable)
一.展示效果(treetable基本样式https://www.cnblogs.com/shuihanxiao/p/10413454.html) 二.html文件(若一个页面又多个treetable, ...
- 手把手入门docker (好多图)
1.什么是docker? ---->我的理解是将许多应用一起打包成一个镜像,拿这个镜像去其他服务器上运行起来就可以.不需要单个单个去配置啦. 2.怎样在window下的安装. ---->刚 ...