• BZOJ3171:[TJOI2013]循环格


    Description

    一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子。每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0)。给定一个起始位置(r,c)

    ,你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,即如果走出边界,你会出现在另一侧。
    一个完美的循环格是这样定义的:对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。给定一个循环格,你需要计算最少需要修改多少个元素使其完美。

    Input

    第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。

    Output

    一个整数,表示最少需要修改多少个元素使得给定的循环格完美

    Sample Input

    3 4
    RRRD
    URLL
    LRRR

    Sample Output

    2

    HINT

    1<=R,L<=15

    题解:

    把原图看做是基环树,则要求每个点都在环上,即每个点有且只有一个子节点。

    把每个点拆成两个,我们得到了一个二分图匹配的模型,其中有些匹配边有代价。

    跑km或费用流即可。

    代码:

     1 const
     2   fx:array[1..4]of longint=(0,1,0,-1);
     3   fy:array[1..4]of longint=(1,0,-1,0);
     4 var
     5   o,v:array[0..1600] of boolean;
     6   f,s,d,dis:array[0..1600] of longint;
     7   next,p,c,w:array[-100000..100000] of longint;
     8   i,j,k,ii,jj,l,y,t,ss,tt,n,m,ans,imp,flow:longint;
     9   ch:array[0..20,0..20]of char;
    10 procedure link(i,j,k,l:longint);
    11 begin
    12   inc(t);
    13   next[t]:=d[i]; d[i]:=t; p[t]:=j; c[t]:=k; w[t]:=l;
    14   next[-t]:=d[j]; d[j]:=-t; p[-t]:=i; w[-t]:=-l;
    15 end;
    16 function dfs(i,flow:longint):longint;
    17 var j,k,l,min:longint;
    18 begin
    19   if i=tt then
    20   begin
    21     inc(ans,dis[i]*flow); exit(flow);
    22   end;
    23   k:=s[i]; j:=p[k]; dfs:=0;
    24   o[i]:=true; v[i]:=true;
    25   while k<>0 do
    26   begin
    27     l:=dis[i]+w[k]-dis[j]; min:=flow;
    28     if c[k]<min then min:=c[k];
    29     if(min>0)and(l<f[j])then f[j]:=l;
    30     if(min>0)and(l=0)and(not o[j])then
    31     begin
    32       l:=dfs(j,min);
    33       inc(dfs,l); dec(flow,l);
    34       dec(c[k],l); inc(c[-k],l);
    35     end;
    36     if flow=0 then break;
    37     s[i]:=next[s[i]];
    38     k:=s[i]; j:=p[k];
    39   end;
    40   o[i]:=false;
    41 end;
    42 begin
    43   readln(n,m);
    44   ss:=0; tt:=n*m*2+1;
    45   for i:=1 to n do
    46   begin
    47     for j:=1 to m do read(ch[i,j]);
    48     readln;
    49   end;
    50   for i:=1 to n do
    51   for j:=1 to m do
    52   begin
    53     link(ss,m*(i-1)+j,1,0); link(n*m+m*(i-1)+j,tt,1,0);
    54     begin
    55       k:=1; ii:=i-1; jj:=j; if ii=0 then ii:=n;
    56       if ch[i,j]='U' then k:=0;
    57       link(m*(i-1)+j,n*m+m*(ii-1)+jj,1,k);
    58     end;
    59     begin
    60       k:=1; ii:=i; jj:=j-1; if jj=0 then jj:=m;
    61       if ch[i,j]='L' then k:=0;
    62       link(m*(i-1)+j,n*m+m*(ii-1)+jj,1,k);
    63     end;
    64     begin
    65       k:=1; ii:=i+1; jj:=j; if ii>n then ii:=1;
    66       if ch[i,j]='D' then k:=0;
    67       link(m*(i-1)+j,n*m+m*(ii-1)+jj,1,k);
    68     end;
    69     begin
    70       k:=1; ii:=i; jj:=j+1; if jj>m then jj:=1;
    71       if ch[i,j]='R' then k:=0;
    72       link(m*(i-1)+j,n*m+m*(ii-1)+jj,1,k);
    73     end;
    74   end;
    75   repeat
    76     for i:=ss to tt do s[i]:=d[i];
    77     fillchar(v,sizeof(v),false);
    78     fillchar(f,sizeof(f),1);
    79     inc(flow,dfs(ss,1 shl 20));
    80     imp:=1 shl 20;
    81     for i:=ss to tt do
    82     if(not v[i])and(f[i]<imp)then imp:=f[i];
    83     for i:=ss to tt do if not v[i] then inc(dis[i],imp);
    84   until imp=1 shl 20;
    85   writeln(ans);
    86 end.
    View Code
  • 相关阅读:
    collections queue、os、datetime,序列化(json和pickle)模块
    re模块和正则
    模块介绍
    迭代器,生成器,生成器表达式,常用内置方法
    交互式shell和非交互式shell的区别
    /usr 的由来及/usr目录结
    Hadoop
    联通、联在中文机器上乱码问题
    正斜杠与反斜杠
    java中static关键字解析
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6513667.html
Copyright © 2020-2023  润新知