1. 程式人生 > >UVA - 1218 Perfect Service (樹形dp)(inf相加溢出)

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

解法 struct tps fff 溢出 解決方法 href bit 正常的

題目鏈接

題意:給你一個樹形圖,讓你把其中若幹個結點染成黑色,其余的染成白色,使得任意一個白色結點都恰好與一個黑色結點相鄰。

解法比較容易,和樹上的最大獨立集類似,取一個結點作為樹根,對每個結點分三種情況討論即可:自己是黑色,自己是白色而父親是黑色,自己和父親都是白色。

但關鍵在於這道題如果用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 }

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