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
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.