【P2387】魔法森林(SPFA非正解)

  题目链接

  不会LCTqwq,看题解似乎SPFA也可以。

  把边按a排序,从小到大每加一条边就以b为距离跑一遍SPFA,类似于Kruskal的想法吧……

  貌似是个暴力

  (luoguLCT模块的题我都快通过了,然而还是不会LCT蛤蛤蛤)

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#include<queue>
#define maxn 50050
#define maxm 500500
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

struct Edge{
    int from,next,to,vala,valb;
    bool operator <(const Edge a)const{
        return vala<a.vala;
    }
}edge[maxm],d[maxm];
int head[maxn],num;
inline void add(int from,int to,int vala,int valb){
    edge[++num]=(Edge){from,head[from],to,vala,valb};
    head[from]=num;
}

bool vis[maxn];
int dis[maxn];
int n,m;
int spfa(int sta,int stb){
    queue<int>q;    q.push(1);    q.push(sta);    q.push(stb);
    memset(vis,0,sizeof(vis));    vis[1]=vis[sta]=vis[stb]=1;
    while(!q.empty()){
        int from=q.front();q.pop();    vis[from]=0;
        for(int i=head[from];i;i=edge[i].next){
            int to=edge[i].to;
            if(dis[to]<=max(dis[from],edge[i].valb))    continue;
            dis[to]=max(dis[from],edge[i].valb);
            if(vis[to])    continue;
            vis[to]=1;    q.push(to);
        }
    }
    return dis[n];
}
            
int main(){
    freopen("testdata.in.txt","r",stdin);
    n=read(),m=read();
    for(int i=1;i<=m;++i)    d[i]=(Edge){read(),0,read(),read(),read()};
    sort(d+1,d+m+1);
    memset(dis,127/3,sizeof(dis));    dis[1]=0;
    int ans=0x7fffffff;
    for(int i=1;i<=m;++i){
        add(d[i].from,d[i].to,d[i].vala,d[i].valb);
        add(d[i].to,d[i].from,d[i].vala,d[i].valb);
        int now=d[i].vala+spfa(d[i].from,d[i].to);
        if(now<ans)    ans=now;
    }
    printf("%d\n",ans==707406379?-1:ans);
    return 0;
}

 

posted @ 2018-01-21 08:34  Konoset  阅读(165)  评论(0编辑  收藏  举报