code1173 最优贸易
先正向从1点出发SPFA,获得min[i],就是到达i点能最低购买到的价格,(起始点到i的路上经过的最小值)
然后反向(将图反向),从n点开始SPFA,获得max[i],就是从i点到终点能够卖出的最大的价格,(终止点到i的路上经过的最大值)
然后就是寻找差价最大的i,输出答案即可。
代码:
#include<iostream> #include<cstring> #include<queue> #define MAXM 500005 #define MAXN 100005 #define INF 0x3f3f3f3f using namespace std; int n,m; struct edge{ int to,next; }eg1[MAXM],eg2[MAXM]; int head1[MAXN],head2[MAXN]; int cnt1=0,cnt2=0; int num[MAXN]; int Max[MAXN]; int Min[MAXN]; bool vis[MAXN]; int ans=0; queue<int> q; void add1(int a,int b){ cnt1++; eg1[cnt1].to=b; eg1[cnt1].next=head1[a]; head1[a]=cnt1; } void add2(int a,int b){ cnt2++; eg2[cnt2].to=b; eg2[cnt2].next=head2[a]; head2[a]=cnt2; } int main(){ freopen("1.in","r",stdin); memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); cin>>n>>m; for(int i=1;i<=n;i++)cin>>num[i]; int a,b,c; for(int i=1;i<=m;i++){ cin>>a>>b>>c; if(c==2){ add1(b,a); add2(a,b); } add1(a,b); add2(b,a); } //spfa1 memset(Min,0x3f,sizeof(Min)); memset(vis,false,sizeof(vis)); q.push(1); vis[1]=true; Min[1]=num[1]; while(!q.empty()){ int k=q.front(); q.pop(); vis[k]=false; for(int i=head1[k];i!=-1;i=eg1[i].next){ int u=eg1[i].to; if(Min[u]>Min[k]){ Min[u]=Min[k]; if(!vis[u]){ q.push(u); vis[u]=true; } } if(Min[u]>num[u]){ Min[u]=num[u]; if(!vis[u]){ q.push(u); vis[u]=true; } } } } //spfa2 memset(Max,0xf3,sizeof(Max)); memset(vis,false,sizeof(vis)); q.push(n); vis[n]=true; Max[n]=num[n]; while(!q.empty()){ int k=q.front(); q.pop(); vis[k]=false; for(int i=head2[k];i!=-1;i=eg2[i].next){ int u=eg2[i].to; if(Max[u]<Max[k]){ Max[u]=Max[k]; if(!vis[u]){ q.push(u); vis[u]=true; } } if(Max[u]<num[u]){ Max[u]=num[u]; if(!vis[u]){ q.push(u); vis[u]=true; } } } } ans=0; for(int i=1;i<=n;i++){ //cout<<Min[i]<<' '<<Max[i]<<endl; if(ans<Max[i]-Min[i]){ ans=Max[i]-Min[i]; } } cout<<ans<<endl; return 0; }
一开始疑问没有权值spfa怎么做...学习了!