【NOI2008】 设计路线

题目描述
设计路线
【问题描述】
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%
的分数。

 

题解

 

解法1:简单方程
 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.

 

解法2:复杂方程(朴素)
  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.

 

解法2:复杂方程(优化)
  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.
posted @ 2012-05-22 16:04  datam  阅读(345)  评论(0编辑  收藏  举报