NOIP2018原创模拟赛DAY1 密室

题目描述:https://www.luogu.org/problemnew/show/U38181

读完题之后,我门发现这是一道裸的最短路,写个我们大家都喜欢的SPFA就可以秒过

考场上的思维自以为没有什么问题,随手写完就交了

考完一看发现挂了,一个点都没过,就有点蒙,然后发现是Re

下面的这行代码大家一定要记住(以后都这么写

long long main()

这个悲惨的故事大家一定要铭记在心,然而你以为这就是事情的全部吗?

不不不,我国服被卡王今天就要卡死在这里

我们会发现,这道题目在最后有一个分类讨论,就是有可能Harry一个人去两个房间会更快(主角光环就是nb

因为是无向图,所以天真的我认为只用判断一次,然而我还是太年轻,Harry先去不同的房间好肥的时间可能不同(出题人太巨了)

然后除了这些也就没有什么思维难度了,基本上是个模板题

下面给出代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue> 
using namespace std;
inline long long min(long long a,long long b){return a<b?a:b;}
inline long long max(long long a,long long b){return a>b?a:b;}
inline long long rd()
{
    long long x=0,f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
inline void write(long long x)
{
   
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
long long n,m,k;
long long head[100006],to[1000006],v[1000006],nxt[1000006];
long long total=0;
long long dis[100006];
long long dis2[100006];
long long book[100006];
void add(long long x,long long y,long long z){
    total++;
    to[total]=y;
    v[total]=z;
    nxt[total]=head[x];
    head[x]=total;
    return ;
}
deque <long long> q;
long long vis[100006];
void spfa_r(long long x){//SPFA板子 
    if(book[x]) return ;
    memset(dis,127,sizeof(dis));
    memset(vis,0,sizeof(vis));
    q.push_back(x);
    vis[x]=1;
    dis[x]=0;
    while(!q.empty()){
        long long h=q.front();
        q.pop_front();
        vis[h]=0;
        for(long long e=head[h];e;e=nxt[e]){
            if(book[to[e]]) continue;
            if(dis[to[e]]>dis[h]+v[e]){
                dis[to[e]]=dis[h]+v[e];
                if(!vis[to[e]]){
                    if(!q.empty()&&dis[to[e]]<=dis[q.front()]) q.push_front(to[e]);
                    else q.push_back(to[e]);
                    vis[to[e]]=1;
                }
            }
        }
    }
    return ;
}
void spfa_h(long long x){
    memset(dis2,127,sizeof(dis2));
    memset(vis,0,sizeof(vis));
    q.push_back(x);
    vis[x]=1;
    dis2[x]=0;
    while(!q.empty()){
        long long h=q.front();
        q.pop_front();
        vis[h]=0;
        for(long long e=head[h];e;e=nxt[e]){
            if(dis2[to[e]]>dis2[h]+v[e]){
                dis2[to[e]]=dis2[h]+v[e];
                if(!vis[to[e]]){
                    if(!q.empty()&&dis2[to[e]]<=dis2[q.front()]) q.push_front(to[e]);
                    else q.push_back(to[e]);
                    vis[to[e]]=1;
                }
            }
        }
    }
    return ;
}
int main()
{
    n=rd(),m=rd(),k=rd();
    for(long long i=1;i<=k;i++){
        long long x=rd();
        book[x]=1;
    }
    for(long long i=1;i<=m;i++){
        long long x=rd(),y=rd(),z=rd();
        add(x,y,z);
        add(y,x,z);
    }
    long long l=rd(),r=rd();
    spfa_r(1);//因为有的房间只有Harry能去 
    spfa_h(1);//所以要分开写(滑稽) 
    long long ans=min(max(dis2[l],dis[r]),max(dis2[r],dis[l]));//两个人去的房间取最优(在这里卡了半天) 
    long long set=dis2[l];
    long long sett=dis2[r];
    spfa_h(l);//Harry先从l点开始 
    ans=min(ans,set+dis2[r]);
    spfa_h(r);//刚才把这行写在了上面 
    ans=min(ans,sett+dis2[l]);
    printf("%lld",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/WWHHTT/p/9696405.html