zoukankan      html  css  js  c++  java
  • BZOJ 3669: [Noi2014]魔法森林 [LCT Kruskal | SPFA]

    题目描述

    为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士。魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…,m。初始时小 E 同学在 1 号节点,隐士则住在 n 号节点。小 E 需要通过这一片魔法森林,才能够拜访到隐士。

    魔法森林中居住了一些妖怪。每当有人经过一条边的时候,这条边上的妖怪 就会对其发起攻击。幸运的是,在 1 号节点住着两种守护精灵:A 型守护精灵与 B 型守护精灵。小 E 可以借助它们的力量,达到自己的目的。

    只要小 E 带上足够多的守护精灵,妖怪们就不会发起攻击了。具体来说,无 向图中的每一条边 ei 包含两个权值 ai 与 bi 。若身上携带的 A 型守护精灵个数不 少于 ai ,且 B 型守护精灵个数不少于 bi ,这条边上的妖怪就不会对通过这条边 的人发起攻击。当且仅当通过这片魔法森林的过程中没有任意一条边的妖怪向 小 E 发起攻击,他才能成功找到隐士。

    由于携带守护精灵是一件非常麻烦的事,小 E 想要知道,要能够成功拜访到 隐士,最少需要携带守护精灵的总个数。守护精灵的总个数为 A 型守护精灵的 个数与 B 型守护精灵的个数之和。

    输入输出格式

    输入格式:

    输入文件的第 1 行包含两个整数 n,m,表示无向图共有 n 个节点,m 条边。 接下来 m 行,第i+ 1 行包含 4 个正整数 Xi,Yi,ai,bi,描述第i条无向边。 其中Xi与 Yi为该边两个端点的标号,ai 与 bi 的含义如题所述。 注意数据中可能包含重边与自环。

    输出格式:

    输出一行一个整数:如果小 E 可以成功拜访到隐士,输出小 E 最少需要携 带的守护精灵的总个数;如果无论如何小 E 都无法拜访到隐士,输出“-1”(不 含引号)。

    输入输出样例

    输入样例#1:
    4 5 
    1 2 19 1 
    2 3 8 12 
    2 4 12 15 
    1 3 17 8 
    3 4 1 17 
    输出样例#1:
    32
    
    输入样例#2:
    3 1 
    1 2 1 1 
    输出样例#2:
    -1

    考虑两个权值的MST?
    a排序后b无序啊,LCT是可以维护动态加边的MST的啊
    这里不会有连通块分开,所以判连通在用个并查集能快一点

    还有一种做法,动态加边SPFA,a排序每次加入边权值为b和边的两个端点到队列。。。。。快了1倍多
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define pa t[x].fa
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    const int N=15e4+5,M=1e5+5,INF=1e9;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n,m,Q,type;
    struct LCTnode{
        int ch[2],fa,rev,w,mx,p;
    }t[N];
    inline int wh(int x){return t[pa].ch[1]==x;}
    inline int isRoot(int x){return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;}
    inline void update(int x){
        t[x].p=x;t[x].mx=t[x].w;
        if(t[lc].mx>t[x].mx) t[x].mx=t[lc].mx,t[x].p=t[lc].p;
        if(t[rc].mx>t[x].mx) t[x].mx=t[rc].mx,t[x].p=t[rc].p;
    }
    inline void rever(int x){
        t[x].rev^=1;
        swap(lc,rc);
    }
    inline void pushDown(int x){
        if(t[x].rev){
            rever(lc);
            rever(rc);
            t[x].rev=0;
        }
    }
    inline void rotate(int x){
        int f=t[x].fa,g=t[f].fa,c=wh(x);
        if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
        t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f;
        t[x].ch[c^1]=f;t[f].fa=x;
        update(f);update(x);
    }
    int st[N],top;
    inline void splay(int x){
        top=0;st[++top]=x;
        for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
        for(int i=top;i>=1;i--) pushDown(st[i]);
        
        for(;!isRoot(x);rotate(x))
            if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
    }
    inline void Access(int x){
        for(int y=0;x;y=x,x=pa){
            splay(x);
            rc=y;
            update(x);
        }
    }
    inline void MakeR(int x){
        Access(x);splay(x);
        rever(x);
    }
    inline int FindR(int x){
        Access(x);splay(x);
        while(lc) x=lc;
        return x;
    }
    inline void Link(int x,int y){
        MakeR(x);
        t[x].fa=y;
    }
    inline void Cut(int x,int y){
        MakeR(x);Access(y);splay(y);
        t[y].ch[0]=t[x].fa=0;
        update(y);
    }
    inline int Que(int x,int y){
        MakeR(x);Access(y);splay(y);
        return t[y].p;
    }
    
    struct edge{
        int u,v,a,b;
        bool operator <(const edge &r)const{return a<r.a;}
    }e[M];
    int ans=INF;
    int fa[N];
    inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void Kruskal(){
        for(int i=1;i<=n;i++) fa[i]=i;
        sort(e+1,e+1+m);
        for(int i=1;i<=m;i++){
            int u=e[i].u,v=e[i].v;
            if(find(u)!=find(v)){
                fa[find(u)]=find(v);
                Link(u,i+n),Link(v,i+n);
                t[i+n].w=t[i+n].mx=e[i].b;
                t[i+n].p=i+n;
            }else{
                int p=Que(u,v);
                if(t[p].w>e[i].b){
                    Cut(e[p-n].u,p),Cut(e[p-n].v,p);
                    Link(u,i+n),Link(v,i+n);
                    t[i+n].w=t[i+n].mx=e[i].b;
                    t[i+n].p=i+n;
                }
            }
            if(find(1)==find(n)) ans=min(ans,e[i].a+t[Que(1,n)].w);
        }
    }
    
    
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();m=read();
        for(int i=1;i<=m;i++) e[i].u=read(),e[i].v=read(),e[i].a=read(),e[i].b=read();
        Kruskal();
        printf("%d",ans==INF?-1:ans);
    }
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int N=5e4+5,M=1e5+5,INF=1e9;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m;
    struct data{
        int u,v,a,b;
        bool operator <(const data &r)const{return a<r.a;}
    }a[M];
    struct edge{
        int v,ne,w;
    }e[M<<1];
    int cnt,h[N];
    inline void ins(int u,int v,int w){
        cnt++;
        e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt;
    }
    int d[N],q[N],head,tail,inq[N];
    inline void lop(int &x){if(x==0) x=N-1;else if(x==N) x=1;}
    inline void push(int v){
        if(d[v]<d[q[head]]) lop(--head),q[head]=v;
        else q[tail++]=v,lop(tail);
        inq[v]=1;
    }
    void spfa(){
        while(head!=tail){
            int u=q[head++];inq[u]=0;lop(head);
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v,w=e[i].w;
                if(d[v]>max(d[u],w)){
                    d[v]=max(d[u],w);
                    if(!inq[v]) push(v);
                }
            }
        }
    }
    int ans=INF;
    void solve(){
        sort(a+1,a+1+m);
        head=tail=1;
        memset(d,0x3f,sizeof(d));
        q[tail++]=1;d[1]=0;inq[1]=1;
        for(int i=1;i<=m;i++){
            ins(a[i].u,a[i].v,a[i].b);
            head=tail=1;
            q[tail++]=a[i].u;inq[a[i].u]=1;
            q[tail++]=a[i].v;inq[a[i].v]=1;
            spfa();
            ans=min(ans,a[i].a+d[n]);
        }
    }
    int main(int argc, const char * argv[]) {
        n=read();m=read();
        for(int i=1;i<=m;i++) a[i].u=read(),a[i].v=read(),a[i].a=read(),a[i].b=read();
        solve();
        printf("%d",ans==INF?-1:ans);
    }


  • 相关阅读:
    XML错误信息Referenced file contains errors (http://www.springframework.org/schema/beans/spring-beans-4.0.xsd). For more information, right click on the message in the Problems View ...
    Description Resource Path Location Type Cannot change version of project facet Dynamic Web Module to 2.3.
    maven创建web报错Cannot read lifecycle mapping metadata for artifact org.apache.maven.plugins:maven-compiler-plugin:maven-compiler-plugin:3.5.1:runtime Cause: error in opening zip file
    AJAX跨域
    JavaWeb学习总结(转载)
    JDBC学习笔记
    Java动态代理之JDK实现和CGlib实现
    (转)看懂UML类图
    spring boot配置使用fastjson
    python3下django连接mysql数据库
  • 原文地址:https://www.cnblogs.com/candy99/p/6282086.html
Copyright © 2011-2022 走看看