您的位置:首页 > 其它

NOIP2009T3最优贸易(Dfs + spfa)

2017-04-07 19:49 316 查看

洛谷传送门

看到这个题,原本想先从后往前dfs,求出能到终点的点,再在这些点里从前往后spfa,用一条边上的两个城市的商品价格的差来作边权,实施过后,发现图中既有负边权,又有回路,以及各种奇奇怪怪的东西。说实话我连样例都没过,然后提交一下试试,得了10分。

然而我发现,要求赚最多钱,就是到那个点的路径上的最大价格 - 最小价格。

两边dfs——

最小价格可以从前往后搜来算。

最大价格可以从后往前搜来算。

最后枚举一边所有点maxx - minn的最大值就好。

说出来你可能不信,我是看的题解。

——代码

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int MAXN = 200001;
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] = 1;
for(i = head1[u]; i != -1; i = next1[i])
{
v = to1[i];
if(!b[v]) dfs(v);
}
}

inline void spfa(int u)
{
int i, v;
memset(dis, 127 / 3, sizeof(dis));
q.push(u);
dis[u] = a[u];
while(!q.empty())
{
u = q.front();
q.pop();
vis[u] = 0;
for(i = head[u]; i != -1; 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] = 1;
}
}
}
}
}

int main()
{
int i, j, x, y, z;
scanf("%d %d", &n, &m);
for(i = 1; i <= n; i++) scanf("%d", &a[i]);
memset(head, -1, sizeof(head));
memset(head1, -1, sizeof(head1));
for(i = 1; i <= m; i++)
{
scanf("%d %d %d", &x, &y, &z);
if(z == 1)
{
add(x, y);
add1(y, x);
}
else
{
add(x, y);
add(y, x);
add1(x, y);
add1(y, x);
}
}
dfs(n);
spfa(1);
for(i = 1; i <= n; i++)
if(b[i])
ans = max(ans, a[i] - dis[i]);
printf("%d", ans);
return 0;
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: