图论-最短路

最短路

  $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 }
最优贸易

猜你喜欢

转载自www.cnblogs.com/shzr/p/9268051.html