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

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 2458  Solved: 1529

    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

    动态SPFA / LCT

    SPFA动态维护花费:

      将边按A权值从小到大排序,依次加边,边权值为B,将新被更新的点加入队列中,跑SPFA。如果本次跑SPFA使得Dis[n]变短了,说明新加入的这条边被用到了,就用A+Dis[n]更新答案。

      

    LCT:

      动态维护最小生成树。仍然是按A权值从小到大排序,依次加边。如果新加入边的两端点已经联通,就从已有路径上找一条权值最大的边CUT掉,再加边。

        试着研发(←并不是)了新的LCT模板,写起来也挺好玩的。还是喜欢把结点信息都扔进一个结构体里那种写法,不过在没有代码补全的时候可能会很吃力吧233

     1 /*by SilverN*/
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 using namespace std;
    10 const int mxn=300010;
    11 int read(){
    12     int x=0,f=1;char ch=getchar();
    13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 struct EGE{
    18     int x,y,a,b;
    19 }EG[mxn];
    20 int cmp(const EGE q,const EGE r){
    21     return q.a<r.a;
    22 }
    23 struct edge{
    24     int v,nxt,w;
    25 }e[mxn<<1];
    26 int hd[mxn],mct=0;
    27 void add_edge(int u,int v,int w){
    28     e[++mct].v=v;e[mct].nxt=hd[u];e[mct].w=w;hd[u]=mct;return;
    29 }
    30 int dis[mxn];
    31 bool inq[mxn];
    32 queue<int>q;
    33 void PS(int x){
    34     q.push(x);inq[x]=1;return;
    35 }
    36 void SPFA(){
    37     while(!q.empty()){
    38         int u=q.front();q.pop();inq[u]=0;
    39         for(int i=hd[u];i;i=e[i].nxt){
    40             int v=e[i].v;
    41             if(dis[v]>max(dis[u],e[i].w)){
    42                 dis[v]=max(dis[u],e[i].w);
    43 //                printf("u%d to v%d :%d %d %d
    ",u,v,dis[u],e[i].w,dis[v]);
    44                 if(!inq[v]){
    45                     inq[v]=1;
    46                     q.push(v);
    47                 }
    48             }
    49         }
    50     }
    51     return;
    52 }
    53 int n,m;
    54 int main(){
    55     int i,j;
    56     n=read();m=read();
    57     for(i=1;i<=m;i++){
    58         EG[i].x=read();    EG[i].y=read();
    59         EG[i].a=read();    EG[i].b=read();
    60     }
    61     memset(dis,0x3f,sizeof dis);
    62     sort(EG+1,EG+m+1,cmp);
    63     int ans=0x3f3f3f3f;
    64     dis[1]=0;
    65     for(i=1;i<=m;i++){
    66         add_edge(EG[i].x,EG[i].y,EG[i].b);
    67         add_edge(EG[i].y,EG[i].x,EG[i].b);
    68         int now=EG[i].a;
    69         if(dis[EG[i].x]>dis[EG[i].y]) PS(EG[i].y);
    70             else PS(EG[i].x);
    71         while(EG[i+1].a==EG[i].a){
    72             i++;
    73             add_edge(EG[i].x,EG[i].y,EG[i].b);
    74             add_edge(EG[i].y,EG[i].x,EG[i].b);
    75             if(dis[EG[i].x]>dis[EG[i].y]) PS(EG[i].y);
    76                 else PS(EG[i].x);
    77         }
    78         int tmp=dis[n];
    79         SPFA();
    80 //        printf("Dis:%d
    ",dis[n]);
    81         ans=min(ans,now+dis[n]);
    82     }
    83     if(dis[n]==0x3f3f3f3f){
    84         printf("-1
    ");
    85         return 0;
    86     }
    87     printf("%d
    ",ans);
    88     return 0;
    89 }
    SPFA
      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int INF=0x3f3f3f3f;
     10 const int mxn=300010;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 inline int max(int x,int y){return x>y?x:y;}
     18 inline int min(int x,int y){return x<y?x:y;}
     19 struct edge{
     20     int x,y,a,b;
     21 }e[mxn<<1];
     22 int cmp(const edge q,const edge r){
     23     return q.a<r.a;
     24 }
     25 int n;
     26 struct LCT{
     27     int ch[mxn][2],fa[mxn];
     28     bool rev[mxn];
     29     int val[mxn],mx[mxn],mxpos[mxn];
     30     void init(int x){
     31         for(int i=0;i<=x;i++){val[i]=0;mxpos[i]=i;mx[i]=-INF;}
     32         return;
     33     }
     34     void add(int x,int w){
     35         val[x]=mx[x]=w;
     36         mxpos[x]=x;
     37         return;
     38     }
     39     inline bool isroot(int x){
     40         return (ch[fa[x]][0]!=x && ch[fa[x]][1]!=x);
     41     }
     42     void pushup(int x){
     43         int lc=ch[x][0],rc=ch[x][1];
     44         mxpos[x]=x;
     45         if(x>n)mx[x]=val[x];else mx[x]=-INF;
     46         if(mx[lc]>mx[x]){mx[x]=mx[lc];mxpos[x]=mxpos[lc];}
     47         if(mx[rc]>mx[x]){mx[x]=mx[rc];mxpos[x]=mxpos[rc];}
     48         return;
     49     }
     50     void PD(int x){
     51         if(rev[x]){
     52             int &lc=ch[x][0],&rc=ch[x][1];
     53             swap(lc,rc);
     54             rev[lc]^=1;rev[rc]^=1;
     55             rev[x]^=1;
     56         }
     57         return;    
     58     }
     59     void rotate(int &x){
     60         int y=fa[x],z=fa[y],lc,rc;
     61         if(ch[y][0]==x)lc=0;else lc=1; rc=lc^1;
     62         if(!isroot(y)){ch[z][ch[z][1]==y]=x;}
     63         fa[y]=x;fa[x]=z;
     64         fa[ch[x][rc]]=y;ch[y][lc]=ch[x][rc];
     65         ch[x][rc]=y;
     66         pushup(y);
     67         return;
     68     }
     69     int st[mxn],top;
     70     void Splay(int x){
     71         st[top=1]=x;
     72         for(int i=x;!isroot(i);i=fa[i])st[++top]=fa[i];
     73         while(top)PD(st[top--]);
     74         while(!isroot(x)){
     75             int y=fa[x],z=fa[y];
     76             if(!isroot(y)){
     77                 if((ch[y][0]==x)^(ch[z][0]==y))rotate(x);
     78                 else rotate(y);
     79             }
     80             rotate(x);
     81         }
     82         pushup(x);
     83         return;
     84     }
     85     void access(int x){
     86         for(int y=0;x;x=fa[x]){
     87             Splay(x);
     88             ch[x][1]=y;
     89             pushup(x);
     90             y=x;
     91         }
     92         return;
     93     }
     94     void mkroot(int x){
     95         access(x);Splay(x);
     96         rev[x]^=1;
     97         return;
     98     }
     99     int find(int x){
    100         access(x);Splay(x);
    101         while(ch[x][0])x=ch[x][0];
    102         return x;
    103     }
    104     void link(int x,int y){
    105         mkroot(x);
    106         fa[x]=y;
    107         return;
    108     }
    109     void cut(int x,int y){
    110         mkroot(x);
    111         access(y);Splay(y);
    112         if(ch[y][0]==x){fa[x]=0;ch[y][0]=0;}
    113         pushup(y);
    114         return;
    115     }
    116     int query(int x,int y){
    117         mkroot(x);access(y);Splay(y);
    118         return mxpos[y];
    119     }
    120 }Lc;
    121 int m;
    122 int id[mxn];
    123 int main(){
    124     int i,j;
    125     n=read();m=read();
    126     Lc.init(n);
    127     for(i=1;i<=m;i++){
    128         e[i].x=read();e[i].y=read();e[i].a=read();e[i].b=read();
    129     }
    130     sort(e+1,e+m+1,cmp);
    131     int cnt=n,ans=0x3f3f3f3f;
    132     for(i=1;i<=m;i++){
    133         int x=e[i].x,y=e[i].y;
    134         Lc.add(++cnt,e[i].b);
    135         id[cnt]=i;
    136         if(Lc.find(x)==Lc.find(y)){
    137             int tmp=Lc.query(x,y);
    138             if(e[i].b>=Lc.mx[y])continue;
    139             Lc.cut(e[id[tmp]].x,tmp);
    140             Lc.cut(e[id[tmp]].y,tmp);
    141         }
    142         Lc.link(x,cnt);
    143         Lc.link(y,cnt);
    144         if(Lc.find(1)==Lc.find(n)){
    145             int tmp=Lc.query(1,n);
    146             ans=min(ans,e[i].a+Lc.mx[tmp]);
    147         }
    148     }
    149     if(ans==0x3f3f3f3f)printf("-1
    ");
    150     else printf("%d
    ",ans);
    151     return 0;
    152 }
    LCT
  • 相关阅读:
    CSS之Position详解
    线性回归预测法linear regression
    置信区间
    asp.net MVC 中使用dataannotation验证Model
    决策树Decision Tree
    Net反射在项目中的应用
    C#并行编程并行任务
    一个特殊的产品价格制定法(市场决定价格)
    Json
    线性规划模型(线性优化模型)Linear programming
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6561787.html
Copyright © 2011-2022 走看看