zoukankan      html  css  js  c++  java
  • BZOJ3876:[AHOI2014]支线剧情

    Description

    【故事背景】
    宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等。不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩怨情仇的剧情。
    这些游戏往往都有很多的支线剧情,现在JYY想花费最少的时间看完所有的支线剧情。
    【问题描述】
    JYY现在所玩的RPG游戏中,一共有N个剧情点,由1到N编号,第i个剧情点可以根据JYY的不同的选择,而经过不同的支线剧情,前往Ki种不同的新的剧情点。当然如果为0,则说明i号剧情点是游戏的一个结局了。
    JYY观看一个支线剧情需要一定的时间。JYY一开始处在1号剧情点,也就是游戏的开始。显然任何一个剧情点都是从1号剧情点可达的。此外,随着游戏的进行,剧情是不可逆的。所以游戏保证从任意剧情点出发,都不能再回到这个剧情点。由于JYY过度使用修改器,导致游戏的“存档”和“读档”功能损坏了,
    所以JYY要想回到之前的剧情点,唯一的方法就是退出当前游戏,并开始新的游戏,也就是回到1号剧情点。JYY可以在任何时刻退出游戏并重新开始。不断开始新的游戏重复观看已经看过的剧情是很痛苦,JYY希望花费最少的时间,看完所有不同的支线剧情。

    Input

    输入一行包含一个正整数N。
    接下来N行,第i行为i号剧情点的信息;
    第一个整数为,接下来个整数对,Bij和Tij,表示从剧情点i可以前往剧
    情点,并且观看这段支线剧情需要花费的时间。

    Output

    输出一行包含一个整数,表示JYY看完所有支线剧情所需要的最少时间。

    Sample Input

    6
    2 2 1 3 2
    2 4 3 5 4
    2 5 5 6 6
    0
    0
    0

    Sample Output

    24

    HINT

    对于100%的数据满足N<=300,0<=Ki<=50,1<=Tij<=300,Sigma(Ki)<=5000
     
    题解:
    这题有点类似BZOJ2324[ZJOI2011]营救皮卡丘,不过此题要求访问每一条边,而非每一个点。
    将每个点i拆成i1与i2,增加i1——>i2的边,容量为inf,费用为0。
    对于出度为x的拓扑节点i,增加x条i2——>T的边,容量为1,费用为对应出边的边权,表示这x条边都要被访问。
    对于入度为x的节点i,增加1条S——>i1的边,容量为x,费用为0,表示这x条入边被访问后,都可以视为从该点重新出发。
    对于点对(i,j),若i点可以到达j点,则增加i1——>j2的边,容量为inf,费用为距离,表示从i点出发走到j点,从而可以访问某个从j点引发的剧情。
    设起点为R,添加一条S——>R1的边,容量为inf,费用为0,表示从起点出发。
    这样建图后,跑一遍zkw费用流即可。
     
    代码:
     1 var
     2   o,v:array[0..1600] of boolean;
     3   f,s,d,dis:array[0..1600] of longint;
     4   next,p,c,w:array[-100000..100000] of longint;
     5   i,j,k,l,y,t,tt,ft,n,ff,st,sf,ans,imp,new,flow:longint;
     6   a:array[0..301,0..301]of longint;
     7   tot:array[0..301]of longint;
     8 procedure link(i,j,k,l:longint);
     9 begin
    10   inc(t);
    11   next[t]:=d[i]; d[i]:=t; p[t]:=j; c[t]:=k; w[t]:=l;
    12   next[-t]:=d[j]; d[j]:=-t; p[-t]:=i; w[-t]:=-l;
    13 end;
    14 function dfs(i,flow:longint):longint;
    15 var j,k,l,min:longint;
    16 begin
    17   if i=tt then
    18   begin
    19     inc(ans,dis[i]*flow); exit(flow);
    20   end;
    21   k:=s[i]; j:=p[k]; dfs:=0;
    22   o[i]:=true; v[i]:=true;
    23   while k<>0 do
    24   begin
    25     l:=dis[i]+w[k]-dis[j]; min:=flow;
    26     if c[k]<min then min:=c[k];
    27     if(min>0)and(l<f[j])then f[j]:=l;
    28     if(min>0)and(l=0)and(not o[j])then
    29     begin
    30       l:=dfs(j,min);
    31       inc(dfs,l); dec(flow,l);
    32       dec(c[k],l); inc(c[-k],l);
    33     end;
    34     if flow=0 then break;
    35     s[i]:=next[s[i]];
    36     k:=s[i]; j:=p[k];
    37   end;
    38   o[i]:=false;
    39 end;
    40 begin
    41   readln(n); tt:=2*n+1;
    42   for i:=1 to n do
    43   for j:=1 to n do a[i,j]:=maxlongint div 2;
    44   for i:=1 to n do
    45   begin
    46     read(k);
    47     for j:=1 to k do
    48     begin
    49       read(l,y);
    50       a[i,l]:=y; inc(tot[l]);
    51       link(i,2*n+1,1,y);
    52     end;
    53   end;
    54   for k:=1 to n do
    55   for i:=1 to n do
    56   for j:=1 to n do
    57   if a[i,k]+a[k,j]<a[i,j] then a[i,j]:=a[i,k]+a[k,j];
    58   for i:=1 to n do
    59   for j:=1 to n do
    60   if(i<>j)and(a[i,j]<maxlongint div 2)then
    61   link(i+n,j,1 shl 20,a[i,j]);
    62   link(0,1+n,1 shl 20,0);
    63   for i:=1 to n do link(0,i+n,tot[i],0);
    64   for i:=1 to n do link(i+n,i,1 shl 20,0);
    65   repeat
    66     for i:=0 to tt do s[i]:=d[i];
    67     fillchar(v,sizeof(v),false);
    68     fillchar(f,sizeof(f),1);
    69     inc(flow,dfs(0,1 shl 20));
    70     imp:=1 shl 20;
    71     for i:=0 to tt do
    72     if(not v[i])and(f[i]<imp)then imp:=f[i];
    73     for i:=0 to tt do if not v[i] then inc(dis[i],imp);
    74   until imp=1 shl 20;
    75   writeln(ans);
    76 end.
    View Code
  • 相关阅读:
    关于overflow:hidden的作用(溢出隐藏、清除浮动、解决外边距塌陷等等)
    float详解
    五 使用并美化网页文本
    代码校验工具 SublimeLinter 的安装与使用
    Sublime Text3 快捷键
    word选择+快捷键
    Word1-提取图片文字
    javascript window对象属性和方法
    word教程字体和段落设置
    Word2 word输入公式+文字转表格
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6262549.html
Copyright © 2011-2022 走看看