最短路
$Floyd$,$Dijkstra$,$SPFA$...
因为听说$SPFA$会被卡,于是一直用堆优化的$dijkstra$......
最优贸易:https://www.luogu.org/problemnew/show/P1073
题意概述:求一条从$1$到$n$的路径,使得这条路径上最大点权的点与最小点权的点相差最大。
其实一看题目感觉还是挺简单的。因为上周末wzx说给我讲$Tarjan$时讲到了这道题,在想的时候很奇妙的先想到了两遍最短路的方法,然而刚刚讲完的$Tarjan$被我遗忘了...
首先想到一个方法,记录从$1$到$i$点的路径上最小的点权是谁,把$i$点就当做最大点权来看,统计答案时把整个图都扫一遍就行了。但是这样还有一个问题,就是有的点虽然可以制造比较大的答案,可是走到它那里以后是不能到达终点的,怎么办呢?反着连边,从终点往前跑最短路,如果能跑到某一个点,正着连边时它必然也可以跑到终点。
再把图正着连回来,像最短路一样更新答案(把松弛条件改一下),就完成了。去年夏令营的课件里提到这才是正解,$Tarjan$加拓扑动归是非常痛苦的一种写法,然而两遍最短路也很痛苦...
1 # include <cstdio> 2 # include <iostream> 3 # include <queue> 4 # include <cstring> 5 # define R register int 6 7 using namespace std; 8 9 const int maxn=100009; 10 const int maxm=500009; 11 int h,n,m,x[maxm],y[maxm],z[maxm],tou[maxn],firs[maxn]; 12 int d[maxn],hig[maxn]; 13 int a[maxn]; 14 bool vis[maxn]; 15 typedef pair <int,int> pii; 16 priority_queue <pii,vector<pii>,greater<pii> > q; 17 struct edge 18 { 19 int nex,too; 20 }g[maxn<<1]; 21 22 int read() 23 { 24 int x=0; 25 char c=getchar(); 26 while (!isdigit(c)) 27 c=getchar(); 28 while (isdigit(c)) 29 { 30 x=(x<<3)+(x<<1)+(c^48); 31 c=getchar(); 32 } 33 return x; 34 } 35 36 void dij1(int s) 37 { 38 memset(d,0x7f,sizeof(d)); 39 d[s]=0; 40 q.push(make_pair(d[s],s)); 41 int beg,j; 42 while (q.size()) 43 { 44 beg=q.top().second; 45 q.pop(); 46 if(vis[beg]) continue; 47 vis[beg]=true; 48 for (R i=firs[beg];i;i=g[i].nex) 49 { 50 j=g[i].too; 51 if(vis[j]) continue; 52 if(d[beg]+1>=d[j]) continue; 53 d[j]=d[beg]+1; 54 q.push(make_pair(d[j],j)); 55 } 56 } 57 } 58 59 void dij2(int s) 60 { 61 while (q.size()) q.pop(); 62 memset(d,0x3f,sizeof(d)); 63 memset(vis,0,sizeof(vis)); 64 d[s]=a[s]; 65 q.push(make_pair(d[s],s)); 66 int beg,j; 67 while (q.size()) 68 { 69 beg=q.top().second; 70 q.pop(); 71 if(vis[beg]) continue; 72 vis[beg]=true; 73 for (R i=firs[beg];i;i=g[i].nex) 74 { 75 j=g[i].too; 76 if(vis[j]) continue; 77 if(d[beg]<d[j]||d[beg]<a[j]) 78 { 79 d[j]=min(d[beg],a[j]); 80 q.push(make_pair(d[j],j)); 81 } 82 } 83 } 84 } 85 86 void add(int x,int y) 87 { 88 g[++h].too=y; 89 g[h].nex=firs[x]; 90 firs[x]=h; 91 } 92 93 int main() 94 { 95 scanf("%d%d",&n,&m); 96 for (int i=1;i<=n;++i) 97 a[i]=read(); 98 for (int i=1;i<=m;++i) 99 { 100 x[i]=read(); 101 y[i]=read(); 102 z[i]=read(); 103 if(z[i]==1) add(y[i],x[i]); 104 else add(x[i],y[i]),add(y[i],x[i]); 105 } 106 dij1(n); 107 for (R i=1;i<=n;++i) 108 if(vis[i]) tou[i]=true; 109 h=0; 110 memset(firs,0,sizeof(firs)); 111 for (R i=1;i<=m;++i) 112 { 113 if(z[i]==1) add(x[i],y[i]); 114 else add(x[i],y[i]),add(y[i],x[i]); 115 } 116 dij2(1); 117 int ans=0; 118 for (R i=1;i<=n;++i) 119 if(tou[i]&&vis[i]) ans=max(ans,a[i]-d[i]); 120 printf("%d",ans); 121 return 0; 122 }