原题地址
https://www.luogu.org/problem/show?pid=1073
图论 最短路
解题思路
双向最短路,先正向建边,从1开始跑一遍求最小值,再反向建边,从n开始再跑一遍求最大值(这里不是指路径长度而是最小、最大点权),完了枚举每个节点,求t[i]=max[i]-min[i],所求即为max(t[i])(1<=i<=n)
参考代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
queue<int>q;
int num1=0,num2=0,n;
int v1[100010],v2[100010],a[100010];
int maxp[100010],minp[100010];
bool vis[100010];
struct mc
{
intx,y,ne;
}e[1000010],p[1000010];
void put1(int x,int y)
{
num1++;
e[num1].x=x;
e[num1].y=y;
e[num1].ne=v1[x];
v1[x]=num1;
}
void put2(int x,int y)
{
num2++;
p[num2].x=x;
p[num2].y=y;
p[num2].ne=v2[x];
v2[x]=num2;
}
void spfa1()
{
memset(minp,127,sizeof(minp));
minp[1]=a[1];
memset(vis,0,sizeof(vis));
q.push(1);
vis[1]=1;
while (!q.empty())
{
intx=q.front();
q.pop();
for(int i=v1[x];i;i=e[i].ne)
{
inty=e[i].y;
if(minp[x]<minp[y])
{
minp[y]=minp[x];
if(minp[y]>a[y])
minp[y]=a[y];
}
if(!vis[y])
{
q.push(y);
vis[y]=1;
}
}
}
}
void spfa2()
{
memset(maxp,0,sizeof(maxp));
maxp[n]=a[n];
memset(vis,0,sizeof(vis));
q.push(n);
vis[n]=1;
while(!q.empty())
{
intx=q.front();
q.pop();
for(int i=v2[x];i;i=p[i].ne)
{
inty=p[i].y;
if(maxp[y]<maxp[x])
{
maxp[y]=maxp[x];
if(maxp[y]<a[y]) maxp[y]=a[y];
}
if(!vis[y])
{
q.push(y);
vis[y]=1;
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
int m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
intx,y,z;
for(int i=1;i<=m;i++)
{
cin>>x>>y>>z;
if(z==1)
{
put1(x,y);
put2(y,x);
}
if(z==2)
{
put1(x,y);
put1(y,x);
put2(x,y);
put2(y,x);
}
}
spfa1();
spfa2();
intans=0;
for(int i=1;i<=n;i++)
if(maxp[i]-minp[i]>ans) ans=maxp[i]-minp[i];
cout<<ans;
return0;
}