Analysis
两遍SPFA
1.求出1~i的路径上点权最小值
m
n
[
i
]
mn[i]
mn[i]
2.求出i~n的路径上点权最大值
m
x
[
i
]
mx[i]
mx[i]
最后枚举每一个点作为出售点,
m
x
[
i
]
−
m
n
[
i
]
mx[i]-mn[i]
mx[i]−mn[i]得到答案
喵喵喵,太妙了!!!
这道题结合了反向建图+SPFA最短路思想
看了题解发现很简单,但自己就是没想到
只能乱搞拿到20分,菜啊……
刚看了题解的时候,以为可以用Topsort来代替SPFA
但仔细想了一下,Topsort一遇到双向边,相当于遇到了环,就咕咕了
还是SPFA好
Summary
注意初始值
今天因为初值太大爆int,贡献了好几发WA
这一定是老天在提醒我NOIP正式考试的时候
一定要注意初始值相加减会不会爆int!!Orz感谢
Code
#include<bits/stdc++.h>
#define in read()
#define N 100009
#define M 1000009
#define inf 105
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<1)+(res<<3)+ch-'0';
ch=getchar();
}
return f==1?res:-res;
}
bool vis[N];
int n,m,val[N],mn[N],mx[N];
int nxt[M],to[M],head[N],ecnt=0;
inline void add(int x,int y){nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;}
int Nxt[M],To[M],Head[N],Ecnt=0;
inline void readd(int x,int y){Nxt[++Ecnt]=Head[x];Head[x]=Ecnt;To[Ecnt]=y;}
inline void spfa1(){
queue<int> q;q.push(1);mn[1]=val[1];
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int e=head[u];e;e=nxt[e]){
int v=to[e];
int tmp=min(mn[u],val[v]);
if(mn[v]>tmp) {
mn[v]=tmp;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
}
inline void spfa2(){
queue<int> q;q.push(n);mx[n]=val[n];
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int e=Head[u];e;e=Nxt[e]){
int v=To[e];
int tmp=max(mx[u],val[v]);
if(mx[v]<tmp) {
mx[v]=tmp;
if(!vis[v]) q.push(v),vis[v]=1;
}
}
}
}
int main(){
n=in;m=in;
int i,j,k,x,y,z;
for(i=1;i<=n;++i) {
val[i]=in;
mx[i]=-inf;mn[i]=inf;
}
for(i=1;i<=m;++i){
x=in;y=in;z=in;
add(x,y);readd(y,x);
if(z==2){add(y,x);readd(x,y);}
}
spfa1();//求出1~i的路径上点权最小值
spfa2();//求出i~n的路径上点权最大值
int ans=0;
for(i=1;i<=n;++i)
ans=max(ans,mx[i]-mn[i]);
cout<<ans;
return 0;
}