1. 程式人生 > >【NOIP2009TG】最優貿易

【NOIP2009TG】最優貿易

本題甚水,可做也。
從1號城市出發,由於最終要到達n號城市,所以我們不妨可以做反向邊,然後從n號城市出發,找到最終可以n號城市的城市,簡單明瞭啊(#^.^#)這樣我們只需要走到標記過的城市即可。
然後,我懶得打太麻煩了。就仔細地想了想,發現每個城市走的次數不可能超過兩次,於是就打了個簡單的bfs,過了。
上標:

#include<cstdio>
#include<algorithm>
using namespace std;
struct node{int v,fr;}e[500010],g[500010];
int n,m,a[100010],tail[100010],head[100010
],cnt=0,tot=0; int f[500010],l,r,d[100010],bz[100010],ans=0; inline int read() { int x=0; char c=getchar(); while (c<'0' || c>'9') c=getchar(); while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x; } void add(int u,int v) {e[++cnt]=(node){v,tail[u]}; tail[u]=cnt;
} void add2(int u,int v) {g[++tot]=(node){v,head[u]}; head[u]=tot;} int main() { freopen("trade.in","r",stdin); // freopen("trade.out","w",stdout); n=read(),m=read(); for (int i=1;i<=n;i++) d[i]=a[i]=read(); for (int i=1,u,v;i<=m;i++) { u=read(),v=read(),add(u,v),add2(v,u); if (read()
==2) add(v,u),add2(u,v); } l=0,r=1;f[1]=n; while (l++<r) { for (int p=head[f[l]],v;p;p=g[p].fr) if (!bz[v=g[p].v]) bz[v=g[p].v]=2,f[++r]=v; } l=0,r=1;f[1]=1; while (l++<r) { for (int p=tail[f[l]],v;p;p=e[p].fr) if (bz[v=e[p].v]--) d[v]=min(d[v],d[f[l]]),f[++r]=v; } for (int i=1;i<=n;i++) ans=max(ans,a[i]-d[i]); printf("%d\n",ans); return 0; }