【NOIP2009提高】藍書(演算法競賽進階指南)刷題記錄——luogu1037最優貿易
阿新 • • 發佈:2018-12-14
題目:給出一張圖,求出兩個點p和q的點權差(一定是p-q)最大,且從點p一定要能便利到點q.
解法一:
這道題我們若是一張有向無環圖的話,我們可以直接跑一個DP,其中推出一個dis0[i]表示從點1到點i的點權最小值,dis1[i]表示從點i到點n上的點權最大值,然後暴力枚舉出最大的dis1[i]-dis0[i].
當有環時,我們可以用最短路代替DP,同樣也是跑dis1和dis0,然後暴力枚舉出答案.用spfa時間複雜度為,用堆優化dijkstra時間複雜度為.
由於一開始覺得自己dijkstra寫的沒有spfa熟,就想寫個堆優化spfa的,然後突然發現還是堆優化dijkstra好寫,就沒改函式名...
程式碼如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=100000,M=500000; const int INF=(1<<30)-1; struct side{ int y,next; }e[M*4+9]; int lin[N+9][2],top; int n,m,v[N+9]; int dis0[N+9],dis1[N+9],ans; bool use[N+9]; struct node{ int x,v; bool operator <(node p)const{ return v<p.v; } bool operator >(node p)const{ return v>p.v; } node(int xx,int vv){ x=xx;v=vv; } }; priority_queue<node> qmax; priority_queue<node,vector<node>,greater<node> > qmin; void ins(int t,int x,int y){ e[++top].y=y; e[top].next=lin[x][t]; lin[x][t]=top; } void spfa0(int sx){ for (int i=1;i<=n;i++) dis0[i]=INF,use[i]=0; qmin.push(node(sx,v[sx])); dis0[sx]=v[sx]; while (!qmin.empty()){ node t=qmin.top();qmin.pop(); if (use[t.x]) continue; use[t.x]=1; for (int i=lin[t.x][0];i;i=e[i].next){ if (min(t.v,v[e[i].y])<dis0[e[i].y]){ dis0[e[i].y]=min(dis0[t.x],v[e[i].y]); qmin.push(node(e[i].y,dis0[e[i].y])); } } } } void spfa1(int sx){ for (int i=1;i<=n;i++) dis1[i]=-INF,use[i]=0; qmax.push(node(sx,v[sx])); dis1[sx]=v[sx]; while (!qmax.empty()){ node t=qmax.top();qmax.pop(); if (use[t.x]) continue; use[t.x]=1; for (int i=lin[t.x][1];i;i=e[i].next) if (max(t.v,v[e[i].y])>dis1[e[i].y]){ dis1[e[i].y]=max(dis1[t.x],v[e[i].y]); qmax.push(node(e[i].y,dis1[e[i].y])); } } } Abigail into(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&v[i]); int x,y,z; for (int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); ins(0,x,y);ins(1,y,x); if (z==1) continue; ins(0,y,x);ins(1,x,y); } } Abigail work(){ spfa0(1); spfa1(n); for (int i=1;i<=n;i++) ans=max(ans,dis1[i]-dis0[i]); } Abigail outo(){ printf("%d\n",ans); } int main(){ into(); work(); outo(); return 0; }