C国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市。
任意两个城市之间最多只有一条道路直接相连。
这 m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为1条。
C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。
但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。
商人阿龙来到C国旅游。
当他得知“同一种商品在不同城市的价格可能会不同”这一信息之后,便决定在旅游的同时,利用商品在不同城市中的差价赚一点旅费。
设C国 n 个城市的标号从 1~n,阿龙决定从1号城市出发,并最终在 n 号城市结束自己的旅行。
在旅游的过程中,任何城市可以被重复经过多次,但不要求经过所有 n 个城市。
阿龙通过这样的贸易方式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品——水晶球,并在之后经过的另一个城市卖出这个水晶球,用赚取的差价当做旅费。
因为阿龙主要是来C国旅游,他决定这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。
现在给出 n 个城市的水晶球价格,m 条道路的信息(每条道路所连接的两个城市的编号以及该条道路的通行情况)。
请你告诉阿龙,他最多能赚取多少旅费。
输入格式
第一行包含 2 个正整数 n 和 m,中间用一个空格隔开,分别表示城市的数目和道路的数目。
第二行 n 个正整数,每两个整数之间用一个空格隔开,按标号顺序分别表示这 n 个城市的商品价格。
接下来 m 行,每行有 3 个正整数,x,y,z,每两个整数之间用一个空格隔开。
如果z=1,表示这条道路是城市 x 到城市 y 之间的单向道路;如果z=2,表示这条道路为城市 x 和城市 y 之间的双向道路。
输出格式
一个整数,表示答案。
数据范围
1≤n≤1000001≤n≤100000,
1≤m≤5000001≤m≤500000,
1≤各城市水晶球价格≤100
AC这道题已经是第二遍了,第一次是用别人一个叫DP的代码水过的,尽管我都不知道什么是DP;今天突然有了灵感,自己又写了一遍,用双向SPFA,第一次就过了,和大家分享一下;
#include <bits/stdc++.h> using namespace std; #define N 100000 inline int read() { int x = 0,ff = 1;char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x<<1) + (x<<3) + (ch ^ 48); ch = getchar(); } return x * ff; } inline void write(int x) { if(x < 0) putchar('-'),x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } int a,b,ans; struct node { int y,next; }e1[N<<1],e2[N<<1]; int tot1,lin1[N<<1]; int tot2,lin2[N<<1]; int mon[N<<1],mi[N<<1],ma[N<<1]; int head,tail,q[N<<1],vis[N<<1]; void add1(int xx,int yy) { e1[++tot1].y = yy; e1[tot1].next = lin1[xx]; lin1[xx] = tot1; } void add2(int xx,int yy) { e2[++tot2].y = yy; e2[tot2].next = lin2[xx]; lin2[xx] = tot2; } void SPFA1(int s) { memset(vis,false,sizeof(vis)); memset(mi,0x3f,sizeof(mi)); head = 1,tail = 1; q[1] = s; mi[s] = mon[s]; for(head = 1;head <= tail;++head) { int x = q[head]; vis[x] = false; for(int i = lin1[x],y;i;i = e1[i].next) { if(mi[y = e1[i].y] > mi[x]) { mi[y] = min(mon[y],mi[x]); if(!vis[y]) { vis[y] = true; q[++tail] = y; } } } } } void SPFA2(int s) { memset(vis,false,sizeof(vis)); head = 1,tail = 1; q[1] = s; ma[s] = mon[s]; for(head = 1;head <= tail;++head) { int x = q[head]; vis[x] = false; for(int i = lin2[x],y;i;i = e2[i].next) { if(ma[y = e2[i].y] < ma[x]) { ma[y] = max(mon[y],ma[x]); if(!vis[y]) { vis[y] = true; q[++tail] = y; } } } } } int main() { a = read(); b = read(); for(int i = 1;i <= a;++i) mon[i] = read(); for(int i = 1;i <= b;++i) { int x,y,z; x = read(); y = read(); z = read(); add1(x,y); add2(y,x); if(z == 2) { add1(y,x); add2(x,y); } } SPFA1(1); SPFA2(a); for(int i = 1;i <= a;++i) ans = max(ans,ma[i] - mi[i]); write(ans); return 0; }
下面是第一次的代码,大佬可以参考一下......
#include<bits/stdc++.h> #define INF 0x7f7f7f7f #define MAXN 100005 using namespace std; vector<int> g[MAXN]; int n,m,f[MAXN],mi[MAXN],c[MAXN]; void dfs(int x,int minx,int pre) { int flag=1; minx=min(c[x],minx); if (mi[x]>minx) mi[x]=minx,flag=0; int maxx=max(f[pre],c[x]-minx); if (f[x]<maxx) f[x]=maxx,flag=0; if (flag) return; for (int i=0;i<g[x].size();i++) dfs(g[x][i],minx,x); } int main() { scanf("%d%d",&n,&m); for (int i=0;i<MAXN;i++) mi[i]=INF; for (int i=1;i<=n;i++) scanf("%d",&c[i]); for (int i=1;i<=m;i++) { int t1,t2,t3; scanf("%d%d%d",&t1,&t2,&t3); g[t1].push_back(t2); if (t3==2) g[t2].push_back(t1); } dfs(1,INF,0); printf("%d ",f[n]); return 0; }