UVA - 1218 Perfect Service (树形dp)(inf相加溢出)

题目链接

题意:给你一个树形图,让你把其中若干个结点染成黑色,其余的染成白色,使得任意一个白色结点都恰好与一个黑色结点相邻。

解法比较容易,和树上的最大独立集类似,取一个结点作为树根,对每个结点分三种情况讨论即可:自己是黑色,自己是白色而父亲是黑色,自己和父亲都是白色。

但关键在于这道题如果用inf来作为不合法状态的dp值的话,会导致在dp的过程中有多个inf相加而炸掉!!习惯把inf设成0x3f3f3f3f或者0x7fffffff的选手们要杯具了。

解决方法有很多,比如把inf设小一点,把int改成longlong等等都可以。比较保险的方法是在运算的过程中如果超过inf就立即改成inf,这样只要保证两个inf相加不会溢出就行了,这时候0x3f3f3f3f的好处就体现出来了,两个0x3f3f3f3f相加之后仍不超过int上限。

这是我第一次爆inf的经历,为什么其他的题都不爆inf,偏偏在这道题上爆了呢?我也想不出一个比较中肯的解释,大概是inf的存在就是为了简化判断,而本身没什么实际意义吧,因此会出现不可预料的结果应该也是正常的,引以为戒。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=1e4+10,inf=0x3f3f3f3f;
 5 struct E {int v,nxt;} e[N<<1];
 6 int n,d[N][3],hd[N],ne;
 7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
 8 void dp(int u,int fa) {
 9     for(int i=hd[u]; ~i; i=e[i].nxt) {
10         int v=e[i].v;
11         if(v==fa)continue;
12         dp(v,u);
13     }
14     d[u][0]=1,d[u][1]=0,d[u][2]=inf;
15     for(int i=hd[u]; ~i; i=e[i].nxt) {
16         int v=e[i].v;
17         if(v==fa)continue;
18         d[u][0]+=min(d[v][0],d[v][1]);
19         d[u][0]=min(d[u][0],inf);
20     }
21     for(int i=hd[u]; ~i; i=e[i].nxt) {
22         int v=e[i].v;
23         if(v==fa)continue;
24         d[u][1]+=d[v][2];
25         d[u][1]=min(d[u][1],inf);
26     }
27     for(int i=hd[u]; ~i; i=e[i].nxt) {
28         int v=e[i].v;
29         if(v==fa)continue;
30         d[u][2]=min(d[u][2],d[u][1]+d[v][0]-d[v][2]);
31         d[u][2]=min(d[u][2],inf);
32     }
33 }
34 
35 int main() {
36     while(scanf("%d",&n)==1) {
37         memset(hd,-1,sizeof hd),ne=0;
38         for(int i=1; i<n; ++i) {
39             int u,v;
40             scanf("%d%d",&u,&v);
41             addedge(u,v);
42             addedge(v,u);
43         }
44         dp(1,-1);
45         printf("%d\n",min(d[1][0],d[1][2]));
46         int ff;
47         scanf("%d",&ff);
48         if(ff==-1)break;
49     }
50     return 0;
51 }

猜你喜欢

转载自www.cnblogs.com/asdfsag/p/10372272.html