【NOI2008】 设计路线
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
设计路线 【问题描述】 Z 国坐落于遥远而又神奇的东方半岛上,在小 Z 的统治时代公路成为这里主 要的交通手段。Z 国共有 n 座城市,一些城市之间由双向的公路所连接。非常神 奇的是 Z 国的每个城市所处的经度都不相同,并且最多只和一个位于它东边的 城市直接通过公路相连。 国的首都是 Z 国政治经济文化旅游的中心,每天都有 Z 成千上万的人从 Z 国的其他城市涌向首都。 为了使 Z 国的交通更加便利顺畅, Z 决定在 Z 国的公路系统中确定若干条 小 规划路线,将其中的公路全部改建为铁路。 我们定义每条规划路线为一个长度大于 1 的城市序列,每个城市在该序列中 最多出现一次,序列中相邻的城市之间由公路直接相连(待改建为铁路)。并且, 每个城市最多只能出现在一条规划路线中, 也就是说, 任意两条规划路线不能有 公共部分。 当然在一般情况下是不可能将所有的公路修建为铁路的,因此从有些城市出 发去往首都依然需要通过乘坐长途汽车, 而长途汽车只往返于公路连接的相邻的 城市之间, 因此从某个城市出发可能需要不断地换乘长途汽车和火车才能到达首 都。 我们定义一个城市的“不便利值”为从它出发到首都需要乘坐的长途汽车的 次数,而 Z 国的交通系统的“不便利值”为所有城市的不便利值的最大值,很明 显首都的“不便利值”为 0。小 Z 想知道如何确定规划路线修建铁路使得 Z 国的 交通系统的 “不便利值” 最小, 以及有多少种不同的规划路线的选择方案使得 “不 便利值”达到最小。当然方案总数可能非常大,小 Z 只关心这个天文数字 mod Q 后的值。 注意:规划路线 1-2-3 和规划路线 3-2-1 是等价的,即将一条规划路线翻转 依然认为是等价的。 两个方案不同当且仅当其中一个方案中存在一条规划路线不 属于另一个方案。 【输入格式】 输入文件 design.in 第一行包含三个正整数 N、M、Q,其中 N 表示城市个数, M 表示公路总数,N 个城市从 1~N 编号,其中编号为 1 的是首都。Q 表示上文 提到的设计路线的方法总数的模数。 接下来 M 行, 每行两个不同的正数 ai、 i (1≤ b ai , bi ≤ N)表示有一条公路连接城市 ai 和城市 bi。 输入数据保证一条公路只出现 一次。 【输出格式】 输出文件 design.out 应包含两行。第一行为一个整数,表示最小的“不便利 值” 第二行为一个整数,表示使“不便利值”达到最小时不同的设计路线的方 。 法总数 mod Q 的值。 如果某个城市无法到达首都,则输出两行-1。 【输入样例】 5 4 100 12 45 13 41 【输出样例】 1 10 【样例说明】 以下样例中是 10 种设计路线的方法: (1) 4-5 (2) 1-4-5 (3) 4-5, 1-2 (4) 4-5, 1-3 (5) 4-5, 2-1-3 (6) 2-1-4-5 (7) 3-1-4-5 (8) 1-4 (9) 2-1-4 (10) 3-1-4 【数据规模和约定】 对于 20%的数据,满足 N,M ≤ 10。 对于 50%的数据,满足 N,M ≤ 200。 对于 60%的数据,满足 N,M ≤ 5000。 对于 100%的数据,满足 1 ≤ N,M ≤ 100000,1 ≤ Q ≤ 120000000。 【评分方式】 每个测试点单独评分。对于每个测试点,第一行错则该测试点得零分,否则 若第二行错则该测试点得到 40%的分数。如果两问都答对,该测试点得到 100% 的分数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 (* 2 *Problem: NOI2008 设计路线 3 *Author : Chen Yang 4 *Time : 2012.5.18 5 *State : AC 6 *Memo : 树形DP 7 *) 8 program design; 9 const maxn=100200; 10 type 11 ty1=^ty2; 12 ty2=record 13 x:longint; 14 next:ty1; 15 end; 16 var 17 n,m,q,i,x,y:longint; 18 first:array[0..maxn] of ty1; 19 f:array[0..maxn,0..20,0..3] of int64; 20 //==================== 21 procedure insert(x,y:longint); 22 var 23 p:ty1; 24 begin 25 new(p); 26 p^.x:=y; p^.next:=first[x]; first[x]:=p; 27 end; 28 //==================== 29 procedure modx(var x:int64); 30 begin 31 if (x mod q=0)and(x>0) then x:=q else x:=x mod q; 32 end; 33 //==================== 34 procedure find(x,fa:longint); 35 var 36 f1,f2:int64; 37 p:ty1; 38 begin 39 f[x,i,0]:=1; 40 p:=first[x]; 41 while p<>nil do 42 begin 43 if p^.x<>fa then 44 begin 45 find(p^.x,x); 46 f1:=f[p^.x,i,0]+f[p^.x,i,1]; modx(f1); 47 f2:=f[p^.x,i-1,0]+f[p^.x,i-1,1]+f[p^.x,i-1,2]; modx(f2); 48 f[x,i,2]:=f[x,i,2]*f2+f[x,i,1]*f1; modx(f[x,i,2]); 49 f[x,i,1]:=f[x,i,1]*f2+f[x,i,0]*f1; modx(f[x,i,1]); 50 f[x,i,0]:=f[x,i,0]*f2; modx(f[x,i,0]); 51 end; 52 p:=p^.next; 53 end; 54 end; 55 //==================== 56 begin 57 assign(input,'design.in'); reset(input); 58 assign(output,'design.out'); rewrite(output); 59 read(n,m,q); 60 if m<>n-1 then 61 begin 62 writeln(-1); writeln(-1); 63 close(input); close(output); 64 halt; 65 end; 66 for i:=1 to m do 67 begin 68 read(x,y); 69 insert(x,y); insert(y,x); 70 end; 71 i:=0; 72 while true do 73 begin 74 find(1,0); 75 if f[1,i,0]+f[1,i,1]+f[1,i,2]>0 then 76 begin 77 writeln(i); 78 writeln((f[1,i,0]+f[1,i,1]+f[1,i,2]) mod q); 79 break; 80 end; 81 inc(i); 82 end; 83 close(input); close(output); 84 end.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 (* 2 *Problem: NOI2008 设计路线 3 *Author : Chen Yang 4 *Time : 2012.5.18 5 *State : 50分 6 *Memo : 朴素树形DP 7 *) 8 program design; 9 const maxn=100100; 10 type 11 ty1=^ty2; 12 ty2=record 13 x:longint; 14 next:ty1; 15 end; 16 ty3=array[0..maxn] of ty1; 17 var 18 n,m,q:longint; 19 first,son:ty3; 20 get:array[0..maxn] of boolean; 21 f,g:array[0..maxn,0..20] of int64; 22 v1,v2:array[0..maxn,0..20] of boolean; 23 sson:array[0..maxn] of longint; 24 //================== 25 procedure insert(x,y:longint; var a:ty3); inline; 26 var 27 p:ty1; 28 begin 29 new(p); 30 p^.x:=y; p^.next:=a[x]; a[x]:=p; 31 end; 32 //================== 33 procedure built(x:longint); 34 var 35 p:ty1; 36 begin 37 get[x]:=true; 38 p:=first[x]; 39 while p<>nil do 40 begin 41 if not get[p^.x] then 42 begin 43 insert(x,p^.x,son); 44 inc(sson[x]); built(p^.x); 45 end; 46 p:=p^.next; 47 end; 48 end; 49 //================== 50 procedure get_inf; 51 var 52 i,x,y:longint; 53 begin 54 read(n,m,q); 55 for i:=1 to m do 56 begin 57 read(x,y); 58 insert(x,y,first); insert(y,x,first); 59 end; 60 built(1); 61 for i:=1 to n do 62 if not get[i] then 63 begin 64 writeln(-1); writeln(-1); 65 close(input); close(output); 66 halt; 67 end; 68 end; 69 //================== 70 procedure find(i,b:longint); forward; 71 //================== 72 procedure dp1(x,b:longint); 73 var 74 t,s:int64; 75 v:boolean; 76 i,j,k:ty1; 77 begin 78 t:=0; i:=son[x]; 79 while i<>nil do 80 begin 81 find(i^.x,b); j:=i^.next; 82 while j<>nil do 83 begin 84 if j^.x<>i^.x then 85 begin 86 find(j^.x,b); k:=son[x]; s:=1; v:=true; 87 while k<>nil do 88 begin 89 if (k^.x<>i^.x)and(k^.x<>j^.x) then 90 begin 91 find(k^.x,b-1); 92 s:=(s*(f[k^.x,b-1]+g[k^.x,b-1])) mod q; 93 if (not v1[k^.x,b-1]) and (not v2[k^.x,b-1]) then v:=false; 94 end; 95 k:=k^.next; 96 end; 97 t:=(t+(g[i^.x,b]*g[j^.x,b]*s) mod q) mod q; 98 if v and v2[i^.x,b] and v2[j^.x,b] then v1[x,b]:=true; 99 end; 100 j:=j^.next; 101 end; 102 i:=i^.next; 103 end; 104 f[x,b]:=t; 105 end; 106 //================== 107 procedure dp2(x,b:longint); 108 var 109 t,s,p:int64; 110 v,vx:boolean; 111 i,j:ty1; 112 begin 113 t:=0; i:=son[x]; p:=1; v:=true; 114 while i<>nil do 115 begin 116 find(i^.x,b); j:=son[x]; s:=1; vx:=true; 117 while j<>nil do 118 begin 119 if j^.x<>i^.x then 120 begin 121 find(j^.x,b-1); 122 s:=(s*(f[j^.x,b-1]+g[j^.x,b-1])) mod q; 123 if not v1[j^.x,b-1] and not v2[j^.x,b-1] then vx:=false; 124 end; 125 j:=j^.next; 126 end; 127 t:=(t+g[i^.x,b]*s) mod q; 128 if vx and v2[i^.x,b] then v2[x,b]:=true; 129 find(i^.x,b-1); 130 p:=(p*(f[i^.x,b-1]+g[i^.x,b-1])) mod q; 131 if not v1[i^.x,b-1] and not v2[i^.x,b-1] then v:=false; 132 i:=i^.next; 133 end; 134 g[x,b]:=(t+p) mod q; 135 v2[x,b]:=v2[x,b] or v; 136 end; 137 //================== 138 procedure dp3(x,b:longint); inline; 139 var 140 i,j:ty1; 141 begin 142 i:=son[x]; j:=i^.next; 143 find(i^.x,b); find(j^.x,b); 144 f[x,b]:=(g[i^.x,b]*g[j^.x,b]) mod q; 145 if (f[x,b]>0)or(v2[i^.x,b] and v2[j^.x,b]) then v1[x,b]:=true; 146 end; 147 //================== 148 procedure dp4(x,b:longint); inline; 149 begin 150 find(son[x]^.x,b); 151 g[x,b]:=g[son[x]^.x,b]; 152 v2[x,b]:=v2[son[x]^.x,b]; 153 end; 154 //================== 155 procedure find(i,b:longint); 156 begin 157 if f[i,b]>-1 then exit; 158 if b>0 then 159 begin 160 if sson[i]<2 then f[i,b]:=0 else dp1(i,b); 161 if sson[i]=0 then begin g[i,b]:=1; v2[i,b]:=true; end else dp2(i,b); 162 end else 163 begin 164 if sson[i]<>2 then f[i,b]:=0 else dp3(i,b); 165 if sson[i]=0 then begin g[i,b]:=1; v2[i,b]:=true; end else 166 if sson[i]=1 then dp4(i,b) else g[i,b]:=0; 167 end; 168 end; 169 //================== 170 procedure main; 171 var 172 i:longint; 173 begin 174 fillchar(f,sizeof(f),255); 175 fillchar(g,sizeof(g),255); 176 i:=0; 177 while true do 178 begin 179 find(1,i); 180 if v1[1,i] or v2[1,i] then 181 begin 182 writeln(i); writeln((f[1,i]+g[1,i]) mod q); 183 break; 184 end; 185 inc(i); 186 end; 187 //for i:=1 to n do 188 //writeln(f[i,0],' ',f[i,1],' ',g[i,0],' ',g[i,1]); 189 end; 190 //================== 191 begin 192 assign(input,'design.in'); reset(input); 193 assign(output,'design.out'); rewrite(output); 194 get_inf; 195 main; 196 close(input); close(output); 197 end.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 (* 2 *Problem: NOI2008 设计路线 3 *Author : Chen Yang 4 *Time : 2012.5.18 5 *State : AC 6 *Memo : 优化树形DP 7 *) 8 program design; 9 const maxn=100100; 10 type 11 ty1=^ty2; 12 ty2=record 13 x:longint; 14 next:ty1; 15 end; 16 var 17 n,m,q,tot:longint; 18 first:array[0..maxn] of ty1; 19 get,vp,vs,vc:array[0..maxn] of boolean; 20 f,g:array[0..maxn,0..10] of int64; 21 pre,suf,c:array[0..maxn] of int64; 22 v1,v2:array[0..maxn,0..10] of boolean; 23 sson,fr,en,son:array[0..maxn] of longint; 24 //================== 25 procedure insert(x,y:longint); inline; 26 var 27 p:ty1; 28 begin 29 new(p); 30 p^.x:=y; p^.next:=first[x]; first[x]:=p; 31 end; 32 //================== 33 procedure built(x:longint); 34 var 35 p:ty1; 36 begin 37 get[x]:=true; fr[x]:=tot+1; 38 p:=first[x]; 39 while p<>nil do 40 begin 41 if not get[p^.x] then 42 begin 43 inc(tot); son[tot]:=p^.x; 44 inc(sson[x]); 45 end; 46 p:=p^.next; 47 end; 48 en[x]:=tot; p:=first[x]; 49 while p<>nil do 50 begin 51 if not get[p^.x] then built(p^.x); 52 p:=p^.next; 53 end; 54 end; 55 //================== 56 procedure get_inf; 57 var 58 i,x,y:longint; 59 begin 60 read(n,m,q); 61 for i:=1 to m do 62 begin 63 read(x,y); 64 insert(x,y); insert(y,x); 65 end; 66 built(1); 67 for i:=1 to n do 68 if not get[i] then 69 begin 70 writeln(-1); writeln(-1); 71 close(input); close(output); 72 halt; 73 end; 74 end; 75 //================== 76 procedure find(i,b:longint); forward; 77 //================== 78 procedure prepare(x,b:longint); 79 var 80 i:longint; 81 begin 82 for i:=fr[x] to en[x] do 83 begin 84 find(son[i],b); find(son[i],b-1); 85 end; 86 pre[fr[x]-1]:=1; vp[fr[x]-1]:=true; 87 for i:=fr[x] to en[x] do 88 begin 89 pre[i]:=(pre[i-1]*(f[son[i],b-1]+g[son[i],b-1])) mod q; 90 if not v1[son[i],b-1] and not v2[son[i],b-1] then vp[i]:=false 91 else vp[i]:=vp[i-1]; 92 end; 93 suf[en[x]+1]:=1; vs[en[x]+1]:=true; 94 for i:=en[x] downto fr[x] do 95 begin 96 suf[i]:=(suf[i+1]*(f[son[i],b-1]+g[son[i],b-1])) mod q; 97 if not v1[son[i],b-1] and not v2[son[i],b-1] then vs[i]:=false 98 else vs[i]:=vs[i+1]; 99 end; 100 end; 101 //================== 102 procedure dp1(x,b:longint); 103 var 104 t,s:int64; 105 v:boolean; 106 i,j,k:longint; 107 begin 108 t:=0; 109 c[en[x]]:=g[son[en[x]],b]; vc[en[x]]:=v2[son[en[x]],b]; 110 for i:=en[x]-1 downto fr[x] do 111 begin 112 c[i]:=(c[i+1]*(f[son[i],b-1]+g[son[i],b-1])) mod q+((g[son[i],b]*suf[i+1]) mod q) mod q; 113 if (not vc[i+1] or (not v1[son[i],b-1])and(not v2[son[i],b-1])) and 114 (not v2[son[i],b] or not vs[i+1]) then vc[i]:=false else vc[i]:=vc[i+1]; 115 end; 116 for i:=fr[x] to en[x]-1 do 117 begin 118 t:=(t+(pre[i-1]*g[son[i],b] mod q)*c[i+1]) mod q; 119 if vp[i-1] and v2[son[i],b] and vc[i+1] then v1[x,b]:=true; 120 end; 121 f[x,b]:=t; 122 end; 123 //================== 124 procedure dp2(x,b:longint); 125 var 126 v:boolean; 127 t,p:int64; 128 i:longint; 129 begin 130 t:=0; p:=1; v2[x,b]:=false; v:=true; 131 for i:=fr[x] to en[x] do 132 begin 133 t:=(t+((g[son[i],b]*pre[i-1]) mod q)*suf[i+1]) mod q; 134 if v2[son[i],b] and vp[i-1] and vs[i+1] then v2[x,b]:=true; 135 p:=(p*(f[son[i],b-1]+g[son[i],b-1])) mod q; 136 if not v1[son[i],b-1] and not v2[son[i],b-1] then v:=false; 137 end; 138 g[x,b]:=(t+p) mod q; 139 v2[x,b]:=v2[x,b] or v; 140 end; 141 //================== 142 procedure dp3(x,b:longint); inline; 143 var 144 i,j:longint; 145 begin 146 i:=son[fr[x]]; j:=son[en[x]]; 147 find(i,b); find(j,b); 148 f[x,b]:=(g[i,b]*g[j,b]) mod q; 149 if (f[x,b]>0)or(v2[i,b] and v2[j,b]) then v1[x,b]:=true; 150 end; 151 //================== 152 procedure dp4(x,b:longint); inline; 153 begin 154 find(son[fr[x]],b); 155 g[x,b]:=g[son[fr[x]],b]; 156 v2[x,b]:=v2[son[fr[x]],b]; 157 end; 158 //================== 159 procedure find(i,b:longint); 160 begin 161 if f[i,b]>-1 then exit; 162 if b>0 then 163 begin 164 prepare(i,b); 165 if sson[i]<2 then f[i,b]:=0 else dp1(i,b); 166 if sson[i]=0 then begin g[i,b]:=1; v2[i,b]:=true; end else dp2(i,b); 167 end else 168 begin 169 if sson[i]<>2 then f[i,b]:=0 else dp3(i,b); 170 if sson[i]=0 then begin g[i,b]:=1; v2[i,b]:=true; end else 171 if sson[i]=1 then dp4(i,b) else g[i,b]:=0; 172 end; 173 end; 174 //================== 175 procedure main; 176 var 177 i:longint; 178 begin 179 fillchar(f,sizeof(f),255); 180 fillchar(g,sizeof(g),255); 181 i:=0; 182 while true do 183 begin 184 find(1,i); 185 if v1[1,i] or v2[1,i] then 186 begin 187 writeln(i); writeln((f[1,i]+g[1,i]) mod q); 188 break; 189 end; 190 inc(i); 191 end; 192 end; 193 //================== 194 begin 195 assign(input,'design.in'); reset(input); 196 assign(output,'design.out'); rewrite(output); 197 get_inf; 198 main; 199 close(input); close(output); 200 end.