luogu P1073 最优贸易

    技术2022-07-10  94

    题面传送门 因为只有一次贸易,所以可以枚举中转点。 从点 1 1 1出发跑最小值 S P F A SPFA SPFA,从点 n n n出发跑最大值 S P F A SPFA SPFA,这个贪心应该都懂。 然后枚举中转点,注意跑不到的点不能枚举。 代码实现:

    #include<cstdio> #include<cstring> #include<queue> #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) using namespace std; int n,m,k,x,y,z,anss,now,tots,cur,ans[100039],dfn[100039],low[100039],vis[100039],st[100039],sh,d1[100039],d2[100039],w[100039],in[100039],maxn[100039],minn[100039]; struct yyy{int to,z;}tmp; struct ljb{ int head,h[100039]; yyy f[1000039]; inline void add(int x,int y){ f[++head]=(yyy){y,h[x]}; h[x]=head; } }s1,s2,s3; inline void tarjan(int x){ dfn[x]=low[x]=++now; vis[x]=1; st[++sh]=x; int cur=s1.h[x]; yyy tmp; while(cur!=-1){ tmp=s1.f[cur]; if(!dfn[tmp.to]) tarjan(tmp.to),low[x]=min(low[x],low[tmp.to]); else if(vis[tmp.to])low[x]=min(low[x],low[tmp.to]); cur=tmp.z; } if(dfn[x]==low[x]){ ++tots; while(st[sh+1]!=x){ vis[st[sh]]=0; ans[st[sh]]=tots; maxn[tots]=max(maxn[tots],w[st[sh]]); minn[tots]=min(minn[tots],w[st[sh]]); sh--; } } } queue<int > q; int main(){ //freopen("1.in","r",stdin); register int i; memset(s1.h,-1,sizeof(s1.h)); memset(s2.h,-1,sizeof(s2.h)); memset(s3.h,-1,sizeof(s3.h)); memset(minn,0x3f,sizeof(minn)); memset(d1,0x3f,sizeof(d1)); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&w[i]); for(i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); s1.add(x,y); if(z==2) s1.add(y,x); } for(i=1;i<=n;i++) if(!dfn[i])tarjan(i); for(i=1;i<=n;i++){ cur=s1.h[i]; while(cur!=-1){ tmp=s1.f[cur]; if(ans[i]!=ans[tmp.to]) s2.add(ans[i],ans[tmp.to]),s3.add(ans[tmp.to],ans[i]); cur=tmp.z; } } q.push(ans[1]); d1[ans[1]]=minn[ans[1]]; while(!q.empty()){ now=q.front(); q.pop(); cur=s2.h[now]; while(cur!=-1){ tmp=s2.f[cur]; if(d1[tmp.to]>d1[now]) d1[tmp.to]=min(d1[now],minn[tmp.to]),q.push(tmp.to); cur=tmp.z; } } d2[ans[n]]=maxn[ans[n]]; q.push(ans[n]); while(!q.empty()){ now=q.front(); q.pop(); cur=s3.h[now]; while(cur!=-1){ tmp=s3.f[cur]; if(d2[tmp.to]<d2[now]) d2[tmp.to]=max(d2[now],maxn[tmp.to]),q.push(tmp.to); cur=tmp.z; } } for(i=1;i<=tots;i++) anss=max(anss,d2[i]-d1[i]); printf("%d\n",anss); }
    Processed: 0.012, SQL: 9