bzoj3669 [Noi2014]魔法森林

题目链接

link cut tree

先把边按a排序,用并查集维护连通块,一条边一条边往里面加,1和n连通就更新答案

lct中需要维护当前链的边权最大值,把边权转化为点权:在边中间插一个点,边权赋值到点上

若当前边的b<max(u,v)就要先cut掉u~v路径上的b最大的边

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<string>
  7 #include<cmath>
  8 #include<ctime>
  9 #include<queue>
 10 #include<stack>
 11 #include<map>
 12 #include<set>
 13 #define rre(i,r,l) for(int i=(r);i>=(l);i--)
 14 #define re(i,l,r) for(int i=(l);i<=(r);i++)
 15 #define Clear(a,b) memset(a,b,sizeof(a))
 16 #define inout(x) printf("%d",(x))
 17 #define douin(x) scanf("%lf",&x)
 18 #define strin(x) scanf("%s",(x))
 19 #define LLin(x) scanf("%lld",&x)
 20 #define op operator
 21 #define CSC main
 22 typedef unsigned long long ULL;
 23 typedef const int cint;
 24 typedef long long LL;
 25 using namespace std;
 26 cint inf=2147483647;
 27 void inin(int &ret)
 28 {
 29     ret=0;int f=0;char ch=getchar();
 30     while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
 31     while(ch>='0'&&ch<='9')ret*=10,ret+=ch-'0',ch=getchar();
 32     ret=f?-ret:ret;
 33 }
 34 struct bian
 35 {
 36     int u,v,a,b;
 37     void in(){inin(u),inin(v),inin(a),inin(b);}
 38     bool op < (const bian &rhs)const {return a<rhs.a;}
 39 }bi[100010];
 40 namespace lct
 41 {
 42     int ch[200020][2],w[200020],Max[200020],fa[200020],rev[200020];
 43     bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
 44     void maintain(int x)
 45     {
 46         Max[x]=x;
 47         if(w[Max[x]]<w[Max[ch[x][0]]])Max[x]=Max[ch[x][0]];
 48         if(w[Max[x]]<w[Max[ch[x][1]]])Max[x]=Max[ch[x][1]];
 49     }
 50     void rotate(int x)
 51     {
 52         int y=fa[x],z=fa[y];
 53         if(!isroot(y))ch[z][ch[z][1]==y]=x;
 54         fa[x]=z,fa[y]=x;
 55         int d=ch[y][1]==x;
 56         fa[ch[x][d^1]]=y;
 57         ch[y][d]=ch[x][d^1];
 58         ch[x][d^1]=y;
 59         maintain(y),maintain(x);
 60     }
 61     void down(int x)
 62     {
 63         if(rev[x])
 64         {
 65             swap(ch[x][0],ch[x][1]);
 66             rev[ch[x][0]]^=1;
 67             rev[ch[x][1]]^=1;
 68             rev[x]=0;
 69         }
 70     }
 71     int sta[100010],top;
 72     void splay(int x)
 73     {
 74         top=0;int xx=x;sta[++top]=xx;
 75         while(!isroot(xx))sta[++top]=fa[xx],xx=fa[xx];
 76         while(top)down(sta[top--]);
 77         while(!isroot(x))
 78         {
 79             int y=fa[x],z=fa[y];
 80             if(!isroot(y))
 81                 if((ch[y][1]==x)^(ch[z][1]==y))rotate(x);
 82                 else rotate(y);else ;
 83             rotate(x);
 84         }
 85     }
 86     void access(int x)
 87     {
 88         int temp=0;
 89         while(x)
 90         {
 91             splay(x);
 92             ch[x][1]=temp;
 93             maintain(x);
 94             temp=x,x=fa[x];
 95         }
 96     }
 97     void reverse(int x)
 98     {
 99         access(x),splay(x);rev[x]^=1;
100     }
101     void link(int x,int y)
102     {
103         reverse(x);fa[x]=y;
104     }
105     void cut(int x,int y)
106     {
107         reverse(x),access(y),splay(y),fa[x]=ch[y][0]=0;maintain(y);
108     }
109     int query(int x,int y)
110     {
111         reverse(x),access(y),splay(y);
112         return Max[y];
113     }
114 }
115 int n,m,fa[200020];
116 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
117 int main()
118 {
119     inin(n),inin(m);re(i,1,n)fa[i]=i;
120     re(i,1,m)bi[i].in();int ans=inf;
121     sort(bi+1,bi+m+1);
122     re(i,1,m)
123     {
124         int u=bi[i].u,v=bi[i].v,a=bi[i].a,b=bi[i].b;
125         if(find(u)==find(v))
126         {
127             int temp=lct::query(u,v);
128             if(lct::w[temp]>b)
129             {
130                 lct::cut(temp,bi[temp-n].u);
131                 lct::cut(temp,bi[temp-n].v);
132             }
133             else 
134             {
135                 if(find(1)==find(n))ans=min(ans,a+lct::w[lct::query(1,n)]);
136                 continue;
137             }
138         }
139         else fa[find(u)]=find(v);
140         lct::w[n+i]=b,lct::Max[n+i]=n+i;
141         lct::link(u,n+i),lct::link(v,n+i);
142         if(find(1)==find(n))ans=min(ans,a+lct::w[lct::query(1,n)]);
143     }
144     printf("%d
",ans==inf?-1:ans);
145      return 0;
146 }
原文地址:https://www.cnblogs.com/HugeGun/p/5239938.html