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\n",ans);
120     else puts("-1");
121     return 0;
122 }

 

posted @ 2018-01-24 09:46  大奕哥&VANE  阅读(157)  评论(0编辑  收藏  举报