標籤:else pre 大小 部分 array .com while 開始 n+1
題解:
把ai認為是i的父親,使其連邊,那麼題目給出的關係構成了一個基環樹森林。
對於在環外、指向環的邊(即“樹”的部分),使骰子的每一個面都比其父親大。
觀察1、4範例可以發現一個構造方式:對於一個大小為n環,從第一個點開始,逆著父親邊放入1~n;再從第一個點在環上的兒子開始,逆著父親邊以此放入n+1~2*n,知道放滿n*m個數。
但是這個構造法在範例3中失敗了。事實上,可以證明,只有在像範例3這種環大小為3,骰子面數為4的情況下,該方法會失效。對於這種情況,進行特判。
注意環大小為2或是m<=2的情況,一定無法構造。
代碼:
const bb:array[1..12]of longint=(1,2,4,3,7,5,10,8,6,11,9,12);var i,j,k,l,n,m,cnt:longint; fa,a,b,c:array[0..1001]of longint; d:array[0..1001,0..1001]of longint;procedure ss2(x:longint);var i:longint;begin if a[x]<2 then begin for i:=1 to m do begin inc(cnt); d[x,i]:=cnt; end; a[x]:=2; end; i:=c[x]; while i>0 do begin if a[i]<2 then ss2(i); i:=b[i]; end;end;procedure ss(x:longint);var i,j,k,l,xx:longint;begin a[x]:=1; x:=fa[x]; while a[x]=0 do begin a[x]:=1; x:=fa[x]; end; k:=1; xx:=fa[x]; a[x]:=2; while x<>xx do begin inc(k); a[xx]:=2; xx:=fa[xx]; end; if k<=2 then begin writeln(0); halt; end; if(k=3)and(m=4)then begin for i:=1 to 12 do begin d[x,1+((i-1)div 3)]:=bb[i]; x:=fa[x]; end; end else begin for i:=1 to m do begin l:=cnt+k; for j:=1 to k do begin d[x,i]:=l; dec(l); if j<>k then x:=fa[x]; end; cnt:=cnt+k; end; end; for i:=1 to k do begin ss2(x); x:=fa[x]; end;end;begin readln(n,m); for i:=1 to n do begin read(fa[i]); b[i]:=c[fa[i]]; c[fa[i]]:=i; end; for i:=1 to n do if a[i]=0 then ss(i); for i:=1 to n do begin for j:=1 to m do write(d[i,j],‘ ‘); writeln; end;end.
BZOJ1298骰子的學問