1. 程式人生 > >NOIP2009提高組Day?T3

NOIP2009提高組Day?T3

傳送門

Analysis

兩遍SPFA 1.求出1~i的路徑上點權最小值 mn[i]mn[i] 2.求出i~n的路徑上點權最大值 mx[i]mx[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; }