洛谷P3656 展翅翱翔之时 (はばたきのとき)(洛谷2017.3月赛round1 t4)

题目背景

船が往くよミライへ旅立とう

船只启航 朝未来展开旅途

青い空笑ってる(なにがしたい?)

湛蓝天空露出微笑(想做些什么?)

ヒカリになろうミライを照らしたい

化作光芒吧 想就此照亮未来

輝きは心からあふれ出してもっと先の景色望むんだ

光辉自内心满溢而出 愿能望见更加前方的景色

Ah!やっと手にしたミライチケットかざして…!

Ah!挥舞起终于得手的未来门票…!

我们Aqours,终于闪闪发亮了!

2月25和26日,将是我们登上横滨ARENA演唱的日子!

而且,还要在全日本、甚至全世界的好多影院进行转播呢!

转播好像还是通过中继卫星传输的呢!

未来ずら!

题目描述

不过,好像中继卫星上,出了一些问题呢……

我们的中继卫星一共有N颗,编号成1到N。不过,好像一个中继卫星可以且仅可以单向地从另一颗中继卫星那儿接收数据。

第i颗卫星现在已经被设定到了从第Ai颗卫星 (称为接收源) 那儿接受数据。

不过这些中继卫星的接收源是可以修改的,只不过每次修改要花一定的资金呢。

听说要达成中继的话,这些卫星之间必须两两之间能够互相(直接或间接)通信才行啊。

虽然鞠莉家里很有钱,可是这么大的花费,也得提前准备一下呢。

所以,你能帮我们算算这样子一共最少要花多少钱吗?

输入输出格式

输入格式:

 

第一行1个整数N。

接下来N行,每行2个整数Ai,Ci,表示初始时,第i个中继卫星从第Ai颗卫星处接收数据,以及该卫星调整接收源的所需花费。

 

输出格式:

 

输出一个整数,表示鞠莉所需准备的最小的花费。

输入输出样例

输入样例#1:
4
2 2
1 6
1 3
3 1
输出样例#1:
5

说明

10% N<=10
40% N<=15
70% N<=3000
100% 2<=N<=100000, 1<=Ci<=10^9

以下是彩蛋

事实上LoveLive的直播卫星中继只有一颗星,而且永远都是不加密的。

导致只要有一个卫星锅就可以在家偷偷看直播,也就是传说中的卫星源。

lin_toto: 万代南梦宫都把浅水湾给买了,居然只有回放,只好跑到香港the sky去看+手动滑稽。

至于为什么看转播,eplus表示LoveLive系列演唱会的票大家尽管抽选尽管抢,买得到算我输。

于是lin_toto在去年μ's Final LoveLive的时候拿肉鸡把eplus搞趴下了,然后就买到了。

于是今年eplus连抢票都不让抢了,全抽选,抽得到算我输。

然后lin_toto就去看转播了。

大概是个贪心乱搞题。

先把所有的连有多条边的点上费用较小的边删去,使只剩一条边。

这时可能还有环,然后在环上讨论一下是选环上的最小边还是重新加上以前删掉的某条边再去掉那个点相邻的环上的边,这样乱搞一搞就好了。

然后要特判的就是如果整个图就是一个环,ans=0

吐槽:月赛的时候没开int64,挂成40;后来改了int64,80,怀疑自己算法错了;然后发现自己特判整个图是一个环的时候直接用所有点入度出度都是1判断了,所以就把多个环也判成一个环了;于是然后加了个并查集,过了。

  1 program rrr(input,output);
  2 const
  3   inf=1123456789;
  4 type
  5   etype=record
  6      t,next:longint;
  7      w:int64;
  8   end;
  9 var
 10   e:array[0..100010]of etype;
 11   a,b,siz,father:array[0..100010]of longint;
 12   c:array[0..100010]of int64;
 13   n,i,j,k,cnt:longint;
 14   ans,max,mmax,min:int64;
 15   flag:boolean;
 16   v,vis:array[0..100010]of boolean;
 17 procedure add(x,y:longint;w:int64);
 18 begin
 19    inc(cnt);e[cnt].t:=y;e[cnt].w:=w;e[cnt].next:=a[x];a[x]:=cnt;
 20 end;
 21 function find(k:longint):longint;
 22 begin
 23    if father[k]=k then exit(k);
 24    father[k]:=find(father[k]);
 25    exit(father[k]);
 26 end;
 27 begin
 28    assign(input,'r.in');assign(output,'r.out');reset(input);rewrite(output);
 29    readln(n);
 30    fillchar(a,sizeof(a),0);cnt:=0;fillchar(siz,sizeof(siz),0);
 31    for i:=1 to n do begin readln(b[i],c[i]);inc(siz[b[i]]);add(b[i],i,c[i]); end;
 32    flag:=true;
 33    ans:=0;
 34    for i:=1 to n do
 35       if a[i]<>0 then
 36          begin
 37             j:=a[i];max:=0;
 38             while j<>0 do
 39                begin
 40                   ans:=ans+e[j].w;
 41                   if e[j].w>max then begin k:=e[j].t;max:=e[j].w; end;
 42                   j:=e[j].next;
 43                end;
 44             ans:=ans-max;
 45             j:=a[i];
 46             while j<>0 do begin if e[j].t<>k then b[e[j].t]:=0;j:=e[j].next; end;
 47          end
 48       else flag:=false;
 49    if flag then
 50       begin
 51          for i:=1 to n do father[i]:=i;
 52          for i:=1 to n do
 53             begin
 54                j:=find(i);k:=find(b[i]);
 55                if j<>k then father[j]:=k;
 56             end;
 57          flag:=true;
 58          for i:=2 to n do if find(i)<>find(1) then begin flag:=false;break; end;
 59          if flag then begin write(0);halt; end;
 60       end;
 61    fillchar(v,sizeof(v),false);
 62    fillchar(vis,sizeof(vis),false);
 63    for i:=1 to n do
 64       if not v[i] then
 65          begin
 66             j:=i;flag:=false;
 67             while true do
 68                begin
 69                   if vis[j] then begin flag:=true;break; end;
 70                   if v[j] then break;
 71                   v[j]:=true;vis[j]:=true;
 72                   if b[j]=0 then break else j:=b[j];
 73                end;
 74             k:=i;while vis[k] do begin vis[k]:=false;k:=b[k]; end;
 75             if not flag then continue;
 76             min:=inf;
 77             while not vis[j] do
 78                begin
 79                   vis[j]:=true;
 80                   if c[j]<min then min:=c[j];
 81                   if siz[j]>1 then
 82                      begin
 83                         mmax:=0;max:=0;
 84                         k:=a[j];
 85                         while k<>0 do
 86                            begin
 87                               if e[k].w>mmax then begin max:=mmax;mmax:=e[k].w end
 88                               else if e[k].w>max then max:=e[k].w;
 89                               k:=e[k].next;
 90                            end;
 91                         if mmax-max<min then min:=mmax-max;
 92                      end;
 93                   j:=b[j];
 94                end;
 95             ans:=ans+min;
 96             while vis[j] do begin vis[j]:=false;j:=b[j];end;
 97          end;
 98    write(ans);
 99    close(input);close(output);
100 end.
原文地址:https://www.cnblogs.com/Currier/p/6550379.html