【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
",ans);
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817788.html