【BZOJ3669】魔法森林(LCT)

题意:有一张无向图,每条边有两个权值。求选取一些边使1和n连通,且max(a[i])+max(b[i])最小

2<=n<=50,000

0<=m<=100,000

1<=ai ,bi<=50,000

思路:LCT模板

将a[i]排序,维护路径上b[i]的最大值

因为是无向图且连通情况不变,不用findroot检查是否连通,并查集即可

也许是OI生涯最后一次打LCT

  1 var t:array[0..300000,0..1]of longint;
  2     rev,fa,mx,w,a,b,f,q,x,y:array[0..300000]of longint;
  3     n,m,i,j,u,v,ans,tmp,top:longint;
  4 
  5 procedure swap(var x,y:longint);
  6 var t:longint;
  7 begin
  8  t:=x; x:=y; y:=t;
  9 end;
 10 
 11 function min(x,y:longint):longint;
 12 begin
 13  if x<y then exit(x);
 14  exit(y);
 15 end;
 16 
 17 function isroot(x:longint):boolean;
 18 begin
 19  if (t[fa[x],0]<>x)and(t[fa[x],1]<>x) then exit(true);
 20  exit(false);
 21 end;
 22 
 23 procedure pushup(p:longint);
 24 var l,r:longint;
 25 begin
 26  l:=t[p,0]; r:=t[p,1];
 27  mx[p]:=p;
 28  if w[mx[l]]>w[mx[p]] then mx[p]:=mx[l];
 29  if w[mx[r]]>w[mx[p]] then mx[p]:=mx[r];
 30 end;
 31 
 32 procedure pushdown(p:longint);
 33 var l,r:longint;
 34 begin
 35  l:=t[p,0]; r:=t[p,1];
 36  if rev[p]=1 then
 37  begin
 38   rev[p]:=0; rev[l]:=rev[l] xor 1; rev[r]:=rev[r] xor 1;
 39   swap(t[p,0],t[p,1]);
 40  end;
 41 end;
 42 
 43 procedure rotate(x:longint);
 44 var y,z,l,r:longint;
 45 begin
 46  y:=fa[x]; z:=fa[y];
 47  if t[y,0]=x then l:=0
 48   else l:=1;
 49  r:=l xor 1;
 50  if not isroot(y) then
 51  begin
 52   if t[z,0]=y then t[z,0]:=x
 53    else t[z,1]:=x;
 54  end;
 55  fa[x]:=z; fa[y]:=x; fa[t[x,r]]:=y;
 56  t[y,l]:=t[x,r]; t[x,r]:=y;
 57  pushup(y);
 58  pushup(x);
 59 end;
 60 
 61 procedure splay(x:longint);
 62 var y,z,k:longint;
 63 begin
 64  inc(top); q[top]:=x;
 65  k:=x;
 66  while not isroot(k) do
 67  begin
 68   inc(top); q[top]:=fa[k];
 69   k:=fa[k];
 70  end;
 71  while top>0 do
 72  begin
 73   pushdown(q[top]);
 74   dec(top);
 75  end;
 76 
 77  while not isroot(x) do
 78  begin
 79   y:=fa[x]; z:=fa[y];
 80   if not isroot(y) then
 81   begin
 82    if (t[y,0]=x)xor(t[z,0]=y) then rotate(x)
 83     else rotate(y);
 84   end;
 85   rotate(x);
 86  end;
 87 end;
 88 
 89 procedure access(x:longint);
 90 var k:longint;
 91 begin
 92  k:=0;
 93  while x>0 do
 94  begin
 95   splay(x); t[x,1]:=k; pushup(x);
 96   k:=x; x:=fa[x];
 97  end;
 98 end;
 99 
100 procedure makeroot(x:longint);
101 begin
102  access(x); splay(x); rev[x]:=rev[x] xor 1;
103 end;
104 
105 procedure link(x,y:longint);
106 begin
107  makeroot(x); fa[x]:=y;
108 end;
109 
110 procedure split(x,y:longint);
111 begin
112  makeroot(x); access(y); splay(y);
113 end;
114 
115 procedure cut(x,y:longint);
116 begin
117  makeroot(x); access(y); splay(y); t[y,0]:=0; fa[x]:=0;
118  pushup(y);
119 end;
120 
121 function query(x,y:longint):longint;
122 begin
123  split(x,y);
124  exit(mx[y]);
125 end;
126 
127 procedure qsort(l,r:longint);
128 var i,j,mid:longint;
129 begin
130  i:=l; j:=r; mid:=a[(l+r)>>1];
131  repeat
132   while mid>a[i] do inc(i);
133   while mid<a[j] do dec(j);
134   if i<=j then
135   begin
136    swap(a[i],a[j]);
137    swap(b[i],b[j]);
138    swap(x[i],x[j]);
139    swap(y[i],y[j]);
140    inc(i); dec(j);
141   end;
142  until i>j;
143  if l<j then qsort(l,j);
144  if i<r then qsort(i,r);
145 end;
146 
147 function find(k:longint):longint;
148 begin
149  if f[k]<>k then f[k]:=find(f[k]);
150  exit(f[k]);
151 end;
152 
153 begin
154  assign(input,'bzoj3669.in'); reset(input);
155  assign(output,'bzoj3669.out'); rewrite(output);
156  readln(n,m);
157  for i:=1 to n do f[i]:=i;
158  for i:=1 to m do read(x[i],y[i],a[i],b[i]);
159  qsort(1,m);
160  ans:=maxlongint;
161 
162  for i:=1 to m do
163  begin
164   u:=x[i]; v:=y[i];
165   if find(u)=find(v) then
166   begin
167    tmp:=query(u,v);
168    if w[tmp]>b[i] then
169    begin
170     cut(tmp,x[tmp-n]);
171     cut(tmp,y[tmp-n]);
172    end
173     else
174     begin
175      if find(1)=find(n) then
176      begin
177       tmp:=query(1,n);
178       ans:=min(ans,w[tmp]+a[i]);
179      end;
180      continue;
181     end;
182   end
183    else f[find(u)]:=find(v);
184   w[i+n]:=b[i]; mx[i+n]:=i+n;
185   link(u,i+n); link(v,i+n);
186   if find(1)=find(n) then
187   begin
188    tmp:=query(1,n);
189    ans:=min(ans,w[tmp]+a[i]);
190   end;
191  end;
192  if ans=maxlongint then writeln(-1)
193   else writeln(ans);
194  close(input);
195  close(output);
196 end.
原文地址:https://www.cnblogs.com/myx12345/p/6558576.html