【NOIP2009TG】最優貿易
阿新 • • 發佈:2019-01-01
本題甚水,可做也。
從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;
}