洛谷传送门

看到这个题,原本想先从后往前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)的更多相关文章

  1. NOIP2009T3最优贸易

    洛谷传送门 看到这个题,原本想先从后往前dfs,求出能到终点的点,再在这些点里从前往后spfa,用一条边上的两个城市的商品价格的差来作边权,实施过后,发现图中既有负边权,又有回路,以及各种奇奇怪怪的东 ...

  2. 【题解】洛谷P1073 [NOIP2009TG] 最优贸易(SPFA+分层图)

    次元传送门:洛谷P1073 思路 一开始看题目嗅出了强连通分量的气息 但是嫌长没打 听机房做过的dalao说可以用分层图 从来没用过 就参考题解了解一下 因为每个城市可以走好几次 所以说我们可以在图上 ...

  3. P1073 最优贸易 建立分层图 + spfa

    P1073 最优贸易:https://www.luogu.org/problemnew/show/P1073 题意: 有n个城市,每个城市对A商品有不同的定价,问从1号城市走到n号城市可以最多赚多少差 ...

  4. 洛谷 P1073 最优贸易 最短路+SPFA算法

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 题面 题目链接 P1073 最优贸易 题目描述 C国有 $ n $ 个大城市和 ...

  5. NOIP2009 最优贸易

    3. 最优贸易 (trade.pas/c/cpp) [问题描述] C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间 多只有一条道路直接相连.这 m 条道 ...

  6. 洛谷P1073 最优贸易 [图论,DP]

    题目传送门 最优贸易 题目描述 C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这m 条道路中有一部分为单向通行的道路,一部分为双向 ...

  7. Codevs 1173 最优贸易 2009年NOIP全国联赛提高组

    1173 最优贸易 2009年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description [问题描述] C 国有n ...

  8. Luogu P1073 最优贸易

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双 ...

  9. 洛谷 P1073 最优贸易 解题报告

    P1073 最优贸易 题目描述 \(C\)国有\(n\)个大城市和\(m\)条道路,每条道路连接这\(n\)个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这\(m\)条道路中有一部分 ...

随机推荐

  1. P3372 【模板】线段树 1 区间查询与区间修改

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个 ...

  2. enum,sizeof,typedef

    枚举类型的使用方法 enum是C语言中的一种自定义类型 enum值可以根据需要自定义整形值 第一个定义的enum值默认为0 默认情况下的enum值是在前一个定义值得基础上加1 enum类型的变量只能去 ...

  3. MSComDlg.CommonDialog服务器不能创建对象错误的解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 在JavaScript中弹出打开文件对话框,代码如下: var fileOpenDlg = new ActiveXOb ...

  4. IOS数组

    /*******************************************************************************************NSArray ...

  5. 洛谷 P1361 小猫爬山

    题目描述 WD和LHX饲养了N只小猫,这天,小猫们要去爬山.经历了千辛万苦,小猫们终于爬上了山顶,但是疲倦的它们再也不想徒步走下山了. WD和LHX只好花钱让它们坐索道下山.索道上的缆车最大承重量为W ...

  6. 原生ajax请求的五个步骤

    //第一步,创建XMLHttpRequest对象 var xmlHttp = new XMLHttpRequest(); function CommentAll() { //第二步,注册回调函数 xm ...

  7. FormItem label 属性 可以改成 slot模式 就能加入br回车了 iview

    FormItem label 属性 可以改成 slot模式 就能加入br回车了 iview <FormItem> <div slot='label'>测试文字<br> ...

  8. iview table 已选项的数据 this.$refs.tables.$refs.tablesMain.getSelection()

    iview table 已选项的数据 this.$refs.tables.$refs.tablesMain.getSelection() 由于我这里table组件是套了两层组件 所以是进入了两个层次拿 ...

  9. java程序在一个电脑上只启动一次,只开一个进程

    方案1: 单进程程序可以用端口绑定.程序启动的时候可以尝试看该端口是否已经被占用,如果占用则程序已经启动. 方案2:你可以在java程序中创建一个隐藏文件,程序退出的时候删除这个文件.这样在程序启动的 ...

  10. Vickers Vane Pump Tips - Vane Pump Maintenance Note

    The    Vickers Vane Pump    describes the matters needing attention in the maintenance of the vane p ...