其他分享
首页 > 其他分享> > P1073 [NOIP2009 提高组] 最优贸易 (最短路spfa)

P1073 [NOIP2009 提高组] 最优贸易 (最短路spfa)

作者:互联网

本题就是在一条1-n的路径上找p,q(先经过p),使得q-p最大。

考虑建正反图,正图上求出d[x],表示1-x的路径经过的节点最小值,反图上则从n开始求出f[x],x-n的最大值,最后枚举断点i,取最大的f[i]-d[i]就是答案。

基于动态规划的思想。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e5+10,M=1e6+10;
 4 int head[N],to[M],nxt[M],edge[M],tot;
 5 int n,m,a[N],d[N],f[N];
 6 bool v[N];
 7 queue<int> q;
 8 
 9 void add(int x,int y,int z){
10     nxt[++tot]=head[x];
11     head[x]=tot;
12     to[tot]=y;
13     edge[tot]=z;//1只能正着走,-1只能倒着走,2正反都可以 
14 } 
15 
16 void spfa(int *d,int st,int z){
17     d[st]=a[st];
18     q.push(st);v[st]=true;
19     while(!q.empty()){
20         int x=q.front();
21         q.pop();v[x]=false;
22         for(int i=head[x];i;i=nxt[i]){
23             if(edge[i]==z||edge[i]==2){
24                 int y=to[i];
25                 int val=z==1?min(d[x],a[y]):max(d[x],a[y]);
26                 if(z==1&&d[y]>val||z==-1&&d[y]<val){
27                     d[y]=val;//更新
28                     if(!v[y]) {q.push(y);v[y]=true;} 
29                 }
30             }
31         }
32     }
33 }
34 
35 int main(){
36     scanf("%d%d",&n,&m);
37     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
38     for(int i=1;i<=m;i++){
39         int x,y,z;
40         scanf("%d%d%d",&x,&y,&z);
41         add(x,y,z);
42         add(y,x,z==1?-1:z);
43     } 
44     memset(d,0x3f,sizeof(d));
45     spfa(d,1,1); // 从1出发求前缀min(d),只有1和2的边可以用
46     memset(f,0xcf/*负无穷*/,sizeof(f));
47     spfa(f,n,-1);// 从n出发倒着求后缀max(d),只有-1和2的边可以用
48     int ans=0;
49     for(int i=1;i<=n;i++) ans=max(ans,f[i]-d[i]);
50     printf("%d\n",ans);
51 } 

 

标签:nxt,head,int,NOIP2009,tot,st,spfa,edge,P1073
来源: https://www.cnblogs.com/yhxnoerror/p/16484801.html