zoukankan      html  css  js  c++  java
  • BZOJ3669: [Noi2014]魔法森林

    3669: [Noi2014]魔法森林

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 226  Solved: 127
    [Submit][Status]

    Description

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

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

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

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

    Input

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

    Output

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

    Sample Input

    【输入样例1】
    4 5
    1 2 19 1
    2 3 8 12
    2 4 12 15
    1 3 17 8
    3 4 1 17





    【输入样例2】


    3 1
    1 2 1 1



    Sample Output

    【输出样例1】

    32
    【样例说明1】
    如果小E走路径1→2→4,需要携带19+15=34个守护精灵;
    如果小E走路径1→3→4,需要携带17+17=34个守护精灵;
    如果小E走路径1→2→3→4,需要携带19+17=36个守护精灵;
    如果小E走路径1→3→2→4,需要携带17+15=32个守护精灵。
    综上所述,小E最少需要携带32个守护精灵。



    【输出样例2】


    -1
    【样例说明2】
    小E无法从1号节点到达3号节点,故输出-1。

    HINT

    2<=n<=50,000


    0<=m<=100,000




    1<=ai ,bi<=50,000

    Source

    题解:

    暴力的想法是枚举a的上界,做b的最小生成树。

    而且有一个比较显然的性质是:

    如果可以在一个生成树中加入一条边,使得树的总权值更小,那么一定是(设这条边连接 x,y)x--y原路径上的最大权值<这条边的权值

    删掉这条边,加上新边。

    那么我们只需要用LCT,维护点与点之间的最大权值,将边以a排序,一条一条试图往里面加即可。

    如果x,y不连通直接加入,否则按上述查询x,y的最大值,比较。

    然后每次都更新一下答案。

    需要注意的是,边权可以转化成点权,我们从x,y各向这个新点连边、删边即可。

    代码:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<iostream>
      7 #include<vector>
      8 #include<map>
      9 #include<set>
     10 #include<queue>
     11 #include<string>
     12 #define inf 1000000000
     13 #define maxn 150000+1000
     14 #define eps 1e-10
     15 #define ll long long
     16 #define pa pair<int,int>
     17 #define for0(i,n) for(int i=0;i<=n;i++)
     18 #define for1(i,n) for(int i=1;i<=n;i++)
     19 #define for2(i,x,y) for(int i=x;i<=y;i++)
     20 using namespace std;
     21 inline int read()
     22 {
     23     int x=0,f=1;char ch=getchar();
     24     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     25     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     26     return x*f;
     27 }
     28 struct rec{int x,y,a,b;}e[maxn];
     29 int n,m,ans,fa[maxn],c[maxn][2],sta[maxn],f[maxn],next[maxn],mx[maxn],v[maxn];
     30 bool rev[maxn];
     31 inline bool isroot(int x)
     32 {
     33     return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
     34 }
     35 inline void pushup(int x)
     36 {
     37     mx[x]=x;
     38     if(v[mx[c[x][0]]]>v[mx[x]])mx[x]=mx[c[x][0]];
     39     if(v[mx[c[x][1]]]>v[mx[x]])mx[x]=mx[c[x][1]];
     40 }
     41 inline void rotate(int x)
     42 {
     43     int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1;
     44     if(!isroot(y))c[z][c[z][1]==y]=x;
     45     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
     46     c[y][l]=c[x][r];c[x][r]=y;
     47     pushup(y);pushup(x);
     48 }
     49 inline void pushdown(int x)
     50 {
     51     if(!rev[x])return;
     52     rev[x]^=1;rev[c[x][0]]^=1;rev[c[x][1]]^=1;
     53     swap(c[x][0],c[x][1]);
     54 }
     55 inline void splay(int x)
     56 {
     57     int top=0;sta[++top]=x;
     58     for(int y=x;!isroot(y);y=fa[y])sta[++top]=fa[y];
     59     for(;top;)pushdown(sta[top--]);
     60     while(!isroot(x))
     61     {
     62         int y=fa[x],z=fa[y];
     63         if(!isroot(y))
     64          {
     65              if(c[z][0]==y^c[y][0]==x)rotate(x);else rotate(y);
     66          }
     67         rotate(x); 
     68     }    
     69 }
     70 inline void access(int x)
     71 {
     72     for(int y=0;x;x=fa[x])
     73     {
     74         splay(x);c[x][1]=y;pushup(x);y=x;
     75     }
     76 }
     77 inline void makeroot(int x)
     78 {
     79     access(x);splay(x);rev[x]^=1;
     80 }
     81 inline int ask(int x,int y)
     82 {
     83     makeroot(x);access(y);splay(y);return mx[y];
     84 }
     85 inline void link(int x,int y)
     86 {
     87     makeroot(x);fa[x]=y;splay(x);
     88 }
     89 inline void cut(int x,int y)
     90 {
     91     makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;
     92 }
     93 inline bool cmp(rec x,rec y)
     94 {
     95     return x.a<y.a;
     96 }
     97 inline int find(int x)
     98 {
     99     return f[x]==x?x:f[x]=find(f[x]);
    100 }
    101 int main()
    102 {
    103     freopen("input.txt","r",stdin);
    104     freopen("output.txt","w",stdout);
    105     n=read();m=read();
    106     for1(i,m)e[i].x=read(),e[i].y=read(),e[i].a=read(),e[i].b=read();
    107     sort(e+1,e+m+1,cmp);
    108     for1(i,m)v[n+i]=e[i].b,mx[i]=n+i;
    109     for1(i,n)f[i]=i;
    110     int x,y,z,xx,yy,ans=inf;
    111     for1(i,m)
    112     {
    113        x=e[i].x,y=e[i].y;
    114        xx=find(x);yy=find(y);
    115        if(xx!=yy)
    116         {
    117             f[xx]=yy;
    118             link(x,n+i);link(y,n+i);
    119         }    
    120        else
    121         {
    122             z=ask(x,y);
    123             if(e[i].b<v[z])
    124              {
    125                  cut(e[z-n].x,z);cut(e[z-n].y,z);
    126                  link(x,n+i);link(y,n+i);
    127              }
    128         } 
    129        if(find(1)==find(n))ans=min(ans,v[ask(1,n)]+e[i].a);  
    130     }
    131     printf("%d
    ",ans==inf?-1:ans);
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    LeetCode15 3Sum
    LeetCode10 Regular Expression Matching
    LeetCode20 Valid Parentheses
    LeetCode21 Merge Two Sorted Lists
    LeetCode13 Roman to Integer
    LeetCode12 Integer to Roman
    LeetCode11 Container With Most Water
    LeetCode19 Remove Nth Node From End of List
    LeetCode14 Longest Common Prefix
    LeetCode9 Palindrome Number
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3947376.html
Copyright © 2011-2022 走看看