• BZOJ3669 NOI2014魔法森林


    按a从小到大排序,然后按b建图。

    每次只需要找1~n中最大的b加当前的a计算答案即可。

    这里还有一个小操作就是化边为点,把一条边的边权看做一个点的点权然后多连两条边。

    By:大奕哥

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int N=4e5+10;
      4 int fa[N],ma[N],pos[N],c[N][2],rev[N],s[N],n,m,ans=2e9,w[N];
      5 struct node{
      6     int x,y,a,b;
      7     bool operator <(const node &b)const{
      8         return a<b.a;
      9     }
     10 }a[N];
     11 bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
     12 void pushup(int x)
     13 {
     14     if(rev[x])
     15     {
     16         rev[x]^=1;rev[c[x][0]]^=1;rev[c[x][1]]^=1;
     17         swap(c[x][0],c[x][1]);
     18     }
     19     return;
     20 }
     21 void update(int x)
     22 {
     23     ma[x]=w[x];pos[x]=x;
     24     if(ma[c[x][0]]>ma[x])ma[x]=ma[c[x][0]],pos[x]=pos[c[x][0]];
     25     if(ma[c[x][1]]>ma[x])ma[x]=ma[c[x][1]],pos[x]=pos[c[x][1]];
     26     return;
     27 }
     28 void rotate(int x)
     29 {
     30     int y=fa[x],z=fa[y],l,r;
     31     l=c[y][1]==x;r=l^1;
     32     if(!isroot(y))c[z][c[z][1]==y]=x;
     33     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
     34     c[y][l]=c[x][r];c[x][r]=y;
     35     update(y);update(x);
     36 }
     37 void splay(int x)
     38 {
     39     int top=0,i;
     40     for(i=x;!isroot(i);i=fa[i])s[++top]=i;s[++top]=i;
     41     for(;top;top--)pushup(s[top]);
     42     while(!isroot(x))
     43     {
     44         int y=fa[x],z=fa[y];
     45         if(!isroot(y))
     46         {
     47             if(c[y][0]==x^c[z][0]==y)rotate(x);
     48             else rotate(y);
     49         }
     50         rotate(x);
     51     }
     52     return;
     53 }
     54 void access(int x)
     55 {
     56     int y=0;
     57     while(x)
     58     {
     59         splay(x);
     60         c[x][1]=y;
     61         y=x;x=fa[x];
     62     }
     63 }
     64 void mroot(int x)
     65 {
     66     access(x);splay(x);rev[x]^=1;
     67 }
     68 void link(int x,int y)
     69 {
     70     mroot(x);fa[x]=y;splay(x);
     71 }
     72 void cut(int x,int y)
     73 {
     74     mroot(x);access(y);splay(y);c[y][0]=fa[x]=0;
     75 }
     76 int get(int x)
     77 {
     78     access(x);splay(x);while(c[x][0])x=c[x][0];return x;
     79 }
     80 int main()
     81 {
     82     scanf("%d%d",&n,&m);
     83     for(int i=1;i<=m;++i)
     84     {
     85         scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b);
     86     }
     87     sort(a+1,a+1+m);
     88     for(int i=1;i<=m;++i)
     89     {
     90         w[i+n]=a[i].b;
     91     }
     92     for(int i=1;i<=m;++i)
     93     {
     94         if(a[i].x==a[i].y)continue;
     95         int fx=get(a[i].x),fy=get(a[i].y);
     96         if(fx!=fy)
     97         {
     98             link(a[i].x,i+n);link(i+n,a[i].y);
     99         }
    100         else
    101         {
    102             mroot(a[i].x);access(a[i].y);
    103             splay(a[i].y);int tmp=pos[c[a[i].y][0]];
    104             if(w[tmp]>a[i].b)
    105             {
    106                 cut(tmp,a[tmp-n].x);cut(tmp,a[tmp-n].y);
    107                 link(a[i].x,n+i);link(a[i].y,n+i);
    108             }
    109         }
    110         if(get(1)==get(n))
    111         {
    112             mroot(1);
    113             access(n);
    114             splay(n);
    115             ans=min(ans,a[i].a+ma[c[n][0]]);
    116         }
    117     }
    118     if(ans!=2e9)
    119     printf("%d
    ",ans);
    120     else puts("-1");
    121     return 0;
    122 }
  • 相关阅读:
    产生财务计帐周期
    判断指定年份是否为闰年
    判断是否是闰年
    Regex quick reference
    组合外键(FOREIGN KEY)
    多列组合为主键(PRIMARY KEY)
    获取字符串开始的地址(案例)
    获取字符串结尾的电话号码(案例)
    ms sql server line feed
    如何产生连续时间?(案例)
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8340078.html
Copyright © 2020-2023  润新知