bzoj3669【NOI2014】魔法森林 SPFA

调了一整个晚上一脸懵逼,加了个并查集优化就WA了= =,然而并没能发现

题意就是两个点权的最短路,标准做法LCT维护,当然我们考虑这是随机数据,我们可以用SPFA水

枚举其中一个点权,然后做另外一个点权的最短路,同时需要用许多优化防止TLE

比如因为单调性,于是每次SPFA并不需要把dis数组清0,用优先队列来维护每一次放进去的点不然写起来全是WA之类的

/**************************************************************
    Problem: 3669
    User: BPM136
    Language: C++
    Result: Accepted
    Time:3032 ms
    Memory:8680 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<bitset>
#include<queue>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
#define efo(i,x) for(int i=last[x];i!=0;i=e[i].next)
using namespace std;
inline LL read()
{
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
#define N 50005
#define M 100005
#define inf 1000000007
struct hhx
{
    int f,v;
    hhx(int a,int b):f(b),v(a){}
    bool operator < (const hhx& a)const
    {return a.f<f;}
};
struct edge
{
    int y,next,c;
}e[M*2];
struct bian
{
    int u,v,a,b;
}b[M*2];
int last[N],ne=0;
int n,m,ma,ans=inf;
int h=0,t=1;
int dis[N];bitset<N>inq;
 
bool com(bian a,bian b)
{
    return a.a<b.a;
}
 
void add(int x,int y,int c)
{
    e[++ne].y=y;e[ne].c=c;e[ne].next=last[x];last[x]=ne;
}
void add2(int x,int y,int c)
{
    add(x,y,c);add(y,x,c);
//  cout<<"Bian:"<<min(x,y)<<' '<<max(x,y)<<' '<<c<<endl;
}
 
void init()
{
    n=read(),m=read();int mi1=1000000,miN=1000000;
    fo(i,1,m)
    {
        int u=read(),v=read(),va=read(),vb=read();
        b[i].u=u;
        b[i].v=v;
        b[i].a=va;
        b[i].b=vb;
        if(u==1||v==1)mi1=min(mi1,va);
        if(u==n||v==n)miN=min(miN,va);
    }
    ma=max(mi1,miN);
}
 
priority_queue<hhx>q;
void spfa()
{
    int i,u,v;
    hhx X(0,0);
    while(!q.empty())
    {
        X=q.top();
        q.pop();
        u=X.v;
        inq[u]=0;
        efo(i,u)
        {
            v=e[i].y;
            if(dis[v]>max(dis[u],e[i].c))
            {
                dis[v]=max(dis[u],e[i].c);
                if(!inq[v])
                {
                    inq[v]=1;
                    q.push(hhx(v,dis[v]));
                }
            }
        }
    }
}
 
void checkdis()
{
    cout<<"DIS:";fo(i,1,n)cout<<dis[i]<<' ';cout<<endl;
}
 
void work()
{
    sort(b+1,b+m+1,com);
    add2(b[1].u,b[1].v,b[1].b);
    dis[1]=0;fo(i,2,n)dis[i]=inf;
    inq.reset();
    fo(i,1,m)
    {
        if(b[i].a==b[i-1].a||i==1||b[i].a<ma)
        {
            add2(b[i].u,b[i].v,b[i].b);
            q.push(hhx(b[i].u,dis[b[i].u])),inq[b[i].u]=1;
            q.push(hhx(b[i].v,dis[b[i].v])),inq[b[i].v]=1;
            continue;
        }
        spfa();
        ans=min(ans,b[i-1].a+dis[n]);
        add2(b[i].u,b[i].v,b[i].b);
        q.push(hhx(b[i].u,dis[b[i].u])),inq[b[i].u]=1;
        q.push(hhx(b[i].v,dis[b[i].v])),inq[b[i].v]=1;
    }
    spfa();
    ans=min(ans,b[m].a+dis[n]);
}
 
int main()
{
    init();
    work();
    if(ans==inf)cout<<-1<<endl;else cout<<ans<<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值