【CF733F】Drivers Dissatisfaction(最小瓶颈生成树,倍增)

题意:给出一个图,每条边有权值和花费c,每次花费c能使的权值-1。给出一个预算,求减完权值后的一个最小生成树。

思路:感谢CC大神

        有这样一个结论:最佳方案里必定存在一种,预算全部花费全部分配在一条边上。证明显然,对于任意一组解,都可以在内部再分配预算使总费用更小或不变。

        于是先求出原图的最小生成树,枚举每条边。

        对于在生成树中的,判断使这条边减费是否更优。

        不在生成树上的,找出树上从x[i]到y[i]的路径(唯一)上a[i]最大的边,判断删除那条边并加入减费后的(x[i],y[i])是否更优。

  1 type yjs=record
  2           a:longint;
  3           s:int64;
  4          end;
  5 var f,q,g:array[1..210000,0..19]of longint;
  6     head,vet,next,len,num,a,b,c,x,y,dep,fa,inq,ya,yb:array[1..500000]of longint;
  7     hth,mst,s:int64;
  8     tot,n,m,i,del,k,tx,ty:longint;
  9     t:yjs;
 10 
 11 procedure swap(var x,y:longint);
 12 var t:longint;
 13 begin
 14  t:=x; x:=y; y:=t;
 15 end;
 16 
 17 procedure qsort(l,r:longint);
 18 var i,j,mid:longint;
 19 begin
 20  i:=l; j:=r; mid:=a[(l+r)>>1];
 21  repeat
 22   while mid>a[i] do inc(i);
 23   while mid<a[j] do dec(j);
 24   if i<=j then
 25   begin
 26    swap(a[i],a[j]); swap(b[i],b[j]); swap(c[i],c[j]);
 27    swap(x[i],x[j]); swap(y[i],y[j]);
 28    inc(i); dec(j);
 29   end;
 30  until i>j;
 31  if l<j then qsort(l,j);
 32  if i<r then qsort(i,r);
 33 end;
 34 
 35 procedure add(a,b,c,d:longint);
 36 begin
 37  inc(tot);
 38  next[tot]:=head[a];
 39  vet[tot]:=b;
 40  len[tot]:=c;
 41  num[tot]:=d;
 42  head[a]:=tot;
 43 end;
 44 
 45 function lca(x,y:longint):longint;
 46 var i,d:longint;
 47 begin
 48  if dep[x]<dep[y] then swap(x,y);
 49  d:=dep[x]-dep[y];
 50  for i:=0 to 19 do
 51   if d and (1<<i)>0 then x:=q[x,i];
 52  for i:=19 downto 0 do
 53   if q[x,i]<>q[y,i] then
 54   begin
 55    x:=q[x,i]; y:=q[y,i];
 56   end;
 57  if x=y then exit(x);
 58  exit(q[x,0]);
 59 end;
 60 
 61 function clac(x,y:longint):yjs;
 62 var i,d:longint;
 63     cc:yjs;
 64 begin
 65  if dep[x]<dep[y] then swap(x,y);
 66  d:=dep[x]-dep[y];
 67  cc.a:=0; cc.s:=-maxlongint;
 68  for i:=19 downto 0 do
 69   if d and (1<<i)>0 then
 70   begin
 71    if f[x,i]>cc.s then
 72    begin
 73     cc.a:=g[x,i];
 74     cc.s:=f[x,i];
 75    end;
 76    x:=q[x,i];
 77   end;
 78  exit(cc);
 79 end;
 80 
 81 function ask(x,y:longint):yjs;
 82 var t:longint;
 83     t1,t2:yjs;
 84 begin
 85  t:=lca(x,y);
 86  t1:=clac(x,t);
 87  t2:=clac(y,t);
 88  if t1.s>t2.s then exit(t1);
 89  exit(t2);
 90 end;
 91 
 92 function find(k:longint):longint;
 93 begin
 94  if fa[k]<>k then fa[k]:=find(fa[k]);
 95  find:=fa[k];
 96 end;
 97 
 98 procedure dfs(u,pre:longint);
 99 var e,v,i:longint;
100 begin
101  for i:=1 to 19 do
102  begin
103   if dep[u]<(1<<i) then break;
104   q[u,i]:=q[q[u,i-1],i-1];
105   if f[u,i-1]<f[q[u,i-1],i-1] then
106   begin
107    f[u,i]:=f[q[u,i-1],i-1];
108    g[u,i]:=g[q[u,i-1],i-1];
109   end
110    else
111    begin
112     f[u,i]:=f[u,i-1];
113     g[u,i]:=g[u,i-1];
114    end;
115  end;
116  e:=head[u];
117  while e<>0 do
118  begin
119   v:=vet[e];
120   if v<>pre then
121   begin
122    dep[v]:=dep[u]+1;
123    f[v,0]:=len[e];
124    q[v,0]:=u;
125    g[v,0]:=num[e];
126    dfs(v,u);
127   end;
128   e:=next[e];
129  end;
130 end;
131 
132 begin
133 
134  readln(n,m);
135  for i:=1 to m do read(a[i]);
136  for i:=1 to m do read(b[i]);
137  for i:=1 to m do c[i]:=i;
138  for i:=1 to m do readln(x[i],y[i]);
139  readln(s);
140  ya:=a; yb:=b;
141  qsort(1,m);
142  for i:=1 to n do fa[i]:=i;
143  for i:=1 to m do
144  begin
145   tx:=find(x[i]); ty:=find(y[i]);
146   if tx<>ty then
147   begin
148    fa[ty]:=tx;
149    hth:=hth+a[i];
150    inq[c[i]]:=1;
151    add(x[i],y[i],a[i],c[i]);
152    add(y[i],x[i],a[i],c[i]);
153   end;
154  end;
155  dfs(1,-1);
156  mst:=hth;
157  for i:=1 to m do
158   if inq[c[i]]=1 then
159   begin
160    if mst-s div b[i]<hth then
161    begin
162     hth:=mst-s div b[i];
163     k:=c[i];
164    end;
165   end
166    else
167    begin
168     t:=ask(x[i],y[i]);
169     if mst-ya[t.a]+a[i]-s div b[i]<hth then
170     begin
171      hth:=mst-ya[t.a]+a[i]-s div b[i];
172      k:=c[i];
173      del:=t.a;
174     end;
175    end;
176  writeln(hth);
177  for i:=1 to m do
178  begin
179   if i=del then continue;
180   if i=k then begin writeln(i,' ',ya[i]-s div yb[i]); continue; end;
181   if inq[i]=1 then writeln(i,' ',ya[i]);
182  end;
183 
184 end.
原文地址:https://www.cnblogs.com/myx12345/p/6062000.html