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

    n<=50000,m<=100000的图上,路径有属性Ai和Bi,问从1到n的路径中(Ai的最大值+Bi的最大值)的最小值。

    双属性图论题,常用套路--定一动二。比如说这里可以先按A从小到大排序,然后依次加入图中来考虑怎么计算B。

    方法一:哦,最大值最小,那不是最小生成树吗?会加边的图,那不是LCT维护最小生成树吗?

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 //#include<time.h>
      5 //#include<math.h>
      6 //#include<set>
      7 //#include<queue>
      8 //#include<bitset>
      9 //#include<vector>
     10 #include<algorithm>
     11 #include<stdlib.h>
     12 using namespace std;
     13 
     14 #define LL long long
     15 LL qread()
     16 {
     17     char c; LL s=0; int f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
     18     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
     19 }
     20 
     21 //Pay attention to '-' , LL and double of qread!!!!
     22 
     23 int n,m;
     24 #define maxn 150011
     25 struct LCT
     26 {
     27     struct Node{int son[2],fa,v,Max,maxid; bool rev;}a[maxn];
     28     int n;
     29     void clear(int N) {n=N; a[0].Max=a[0].v=-0x3f3f3f3f;}
     30     void up(int x)
     31     {
     32         if (!x) return;
     33         Node &b=a[x],&c=a[a[x].son[0]],&d=a[a[x].son[1]];
     34         if (b.v>=c.Max && b.v>=d.Max) {b.Max=b.v; b.maxid=x;}
     35         else if (c.Max>=b.v && c.Max>=d.Max) {b.Max=c.Max; b.maxid=c.maxid;}
     36         else {b.Max=d.Max; b.maxid=d.maxid;}
     37     }
     38     void revsingle(int x) {if (!x) return; a[x].rev^=1; swap(a[x].son[0],a[x].son[1]);}
     39     void down(int x) {if (a[x].rev) {revsingle(a[x].son[0]); revsingle(a[x].son[1]); a[x].rev=0;} }
     40     bool isroot(int x) {return !a[x].fa || (x!=a[a[x].fa].son[0] && x!=a[a[x].fa].son[1]);}
     41     void rotate(int x)
     42     {
     43         int y=a[x].fa,z=a[y].fa;
     44         bool w=(x==a[y].son[0]);
     45         a[x].fa=z;
     46         if (!isroot(y)) a[z].son[y==a[z].son[1]]=x;
     47         a[y].son[w^1]=a[x].son[w];
     48         if (a[x].son[w]) a[a[x].son[w]].fa=y;
     49         a[x].son[w]=y;
     50         a[y].fa=x;
     51         up(y); up(z);
     52     }
     53     int sta[maxn],top;
     54     void download(int x)
     55     {
     56         int i=x; while (!isroot(i)) sta[++top]=i,i=a[i].fa; sta[++top]=i;
     57         for (;top;top--) down(sta[top]);
     58     }
     59     void splay(int x)
     60     {
     61         if (!x) return;
     62         download(x);
     63         while (!isroot(x))
     64         {
     65             int y=a[x].fa,z=a[y].fa;
     66             if (!isroot(y)) {if ((x==a[y].son[0])^(y==a[z].son[0])) rotate(x); else rotate(y);}
     67             rotate(x);
     68         }
     69         up(x);
     70     }
     71     void access(int x) {int y=0,z=x; while (x) {splay(x); a[x].son[1]=y; up(x); y=x; x=a[x].fa;} splay(z);}
     72     void reset(int x) {access(x); revsingle(x);}
     73     
     74     void link(int x,int y) {reset(x); a[x].fa=y;}
     75     void cut(int x,int y)
     76     {reset(x); access(y); a[x].fa=a[y].son[0]=0; up(y);}
     77     bool con(int x,int y) {reset(x); while (y) {if (y==x) return 1; y=a[y].fa;} return 0;}
     78     int qmax(int x,int y) {reset(x); access(y); return a[y].maxid;}
     79     
     80 //    void test()
     81 //    {
     82 //        for (int i=1;i<=n;i++) cout<<i<<" fa"<<a[i].fa<<" son0 "<<a[i].son[0]<<" son1 "<<a[i].son[1]
     83 //        <<" v"<<a[i].v<<" Max"<<a[i].Max<<" maxid"<<a[i].maxid<<endl;
     84 //    }
     85 }t;
     86 
     87 struct EE{int x,y,a,b; bool operator < (const EE &b) const {return a<b.a;} }ee[maxn];
     88 int main()
     89 {
     90     n=qread(); m=qread();
     91     for (int i=1;i<=m;i++) {ee[i].x=qread(); ee[i].y=qread(); ee[i].a=qread(); ee[i].b=qread();}
     92     sort(ee+1,ee+1+m);
     93     
     94     int ans=0x3f3f3f3f;
     95     t.clear(n+m);
     96     for (int i=1;i<=n;i++) t.a[i].v=-0x3f3f3f3f,t.a[i].Max=-0x3f3f3f3f,t.a[i].maxid=i;
     97     for (int i=n+1;i<=n+m;i++) t.a[i].v=ee[i-n].b,t.a[i].Max=t.a[i].v,t.a[i].maxid=i;
     98     for (int i=1;i<=m;i++)
     99     {
    100         if (t.con(ee[i].x,ee[i].y))
    101         {
    102             int z=t.qmax(ee[i].x,ee[i].y);
    103             if (t.a[z].v>t.a[i+n].v)
    104             {
    105                 t.cut(ee[z-n].x,z);
    106                 t.cut(ee[z-n].y,z);
    107                 t.link(ee[i].x,i+n);
    108                 t.link(ee[i].y,i+n);
    109             }
    110         }
    111         else {t.link(ee[i].x,i+n); t.link(ee[i].y,i+n); }
    112         if (t.con(1,n)) ans=min(ans,ee[i].a+t.a[t.qmax(1,n)].v);
    113     }
    114     printf("%d
    ",ans==0x3f3f3f3f?-1:ans);
    115     return 0;
    116 }
    View Code

    好久没写了,这次写起来居然这么顺这么短,有点屌。

    方法二:LCT学傻了系列,可以先考虑一个暴力:每次加完边之后做一次最短路。不过加了一条边之后,所有导致每个点的答案被更新的根本原因,来自于这条边两端的点的互相更新。也就是说,每加一条边后,前面图的大部分信息是不用算的,就看一下这条边两端的点能否更新彼此,能的话把被更新的点加入队列再跑最短路就OK。复杂度??玄学,反正比LCT快,好写!

     1 #include<string.h>
     2 #include<stdlib.h>
     3 #include<stdio.h>
     4 #include<math.h>
     5 //#include<assert.h>
     6 #include<algorithm> 
     7 #include<queue>
     8 //#include<iostream>
     9 //#include<bitset>
    10 using namespace std;
    11 
    12 int n,m;
    13 #define maxn 200011
    14 #define maxm 200011
    15 struct List{int from,to,a,b;}list[maxm];
    16 bool cmpa(const List &a,const List &b) {return a.a<b.a;}
    17 struct Edge{int to,next,v;}edge[maxm]; int first[maxn],le=2;
    18 void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
    19 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);}
    20 
    21 struct qnode
    22 {
    23     int id,v;
    24     bool operator > (const qnode &b) const {return v>b.v;}
    25 };
    26 priority_queue<qnode,vector<qnode>,greater<qnode> > q;
    27 int dis[maxn];
    28 
    29 void kick(int x,int y,int ev)
    30 {
    31     if (dis[x]>max(dis[y],ev))
    32     {
    33         dis[x]=max(dis[y],ev);
    34         q.push((qnode){x,dis[x]});
    35     }
    36 }
    37 void dijkstra()
    38 {
    39     while (!q.empty())
    40     {
    41         const int now=q.top().id,d=q.top().v; q.pop();
    42         if (dis[now]<d) continue;
    43         for (int i=first[now];i;i=edge[i].next)
    44         {
    45             const Edge &e=edge[i];
    46             if (dis[e.to]>max(dis[now],e.v))
    47             {
    48                 dis[e.to]=max(dis[now],e.v);
    49                 q.push((qnode){e.to,dis[e.to]});
    50             }
    51         }
    52     }
    53 }
    54 
    55 int main()
    56 {
    57     scanf("%d%d",&n,&m);
    58     for (int i=1;i<=m;i++) scanf("%d%d%d%d",&list[i].from,&list[i].to,&list[i].a,&list[i].b);
    59     sort(list+1,list+1+m,cmpa);
    60     list[m+1].a=0x3f3f3f3f;
    61     for (int i=1;i<=n;i++) dis[i]=0x3f3f3f3f;
    62     dis[1]=0; int ans=0x3f3f3f3f;
    63     for (int i=1,j=1;i<=m;i++) if (list[i].a!=list[i+1].a)
    64     {
    65         for (;j<=i;j++)
    66         {
    67             insert(list[j].from,list[j].to,list[j].b);
    68             kick(list[j].from,list[j].to,list[j].b);
    69             kick(list[j].to,list[j].from,list[j].b);
    70         }
    71         dijkstra();
    72         ans=min(ans,list[i].a+dis[n]);
    73     }
    74     if (ans==0x3f3f3f3f) puts("-1");
    75     else printf("%d
    ",ans);
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    【poj1655】Balancing Act
    yargs.js用法
    8、typescript
    7、typescript
    6、typescript
    5、typescript
    4、typescript
    3、typescript
    2、typescript
    1、typescript
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8294897.html
Copyright © 2011-2022 走看看