bzoj4472: [Jsoi2015]salesman(树形dp)
Description
某售貨員小T要到若干城鎮去推銷商品,由于該地區是交通不便的山區,任意兩個城鎮
之間都只有唯一的可能經過其它城鎮的路線。 小T 可以準確地估計出在每個城鎮停留的凈收
益。這些凈收益可能是負數,即推銷商品的利潤抵不上花費。由于交通不便,小T經過每個
城鎮都需要停留,在每個城鎮的停留次數與在該地的凈收益無關,因為很多費用不是計次收
取的,而每個城鎮對小T的商品需求也是相對固定的,停留一次后就飽和了。每個城鎮為了
強化治安,對外地人的最多停留次數有嚴格的規定。請你幫小T 設計一個收益最大的巡回方
案,即從家鄉出發,在經過的每個城鎮停留,最后回到家鄉的旅行方案。你的程序只需輸出
最大收益,以及最優方案是否唯一。方案并不包括路線的細節,方案相同的標準是選擇經過
并停留的城鎮是否相同。因為取消巡回也是一種方案,因此最大收益不會是負數。小T 在家
鄉凈收益是零,因為在家鄉是本地人,家鄉對小 T當然沒有停留次數的限制。
Input
輸入的第一行是一個正整數n(5<=n<=100000),表示城鎮數目。城鎮以1到n的數命名。小T 的家鄉命
名為1。第二行和第三行都包含以空格隔開的n-1個整數,第二行的第i個數表示在城鎮
i+1停留的凈收益。第三行的第i個數表示城鎮i+1規定的最大停留次數。所有的最大
停留次數都不小于2。接下來的n-1行每行兩個1到n的正整數x,y,之間以一個空格
隔開,表示x,y之間有一條不經過其它城鎮的雙向道路。輸入數據保證所有城鎮是連通的。?
Output
輸出有兩行,第一行包含一個自然數,表示巡回旅行的最大收益。如果該方案唯一,在
第二行輸出“solution is unique”,否則在第二行輸出“solution is not unique”。
Sample Input
9-3 -4 2 4 -2 3 4 6
4 4 2 2 2 2 2 2
1 2
1 3
1 4
2 5
2 6
3 7
4 8
4 9
Sample Output
9solution is unique
//最佳路線包括城鎮 1,2, 4, 5, 9。
這道樹形dp好清奇…… 考慮一下,設$cnt[i]$表示在$i$點的最多停留次數,那么$cnt[i]-1$就是最多能進入的子樹的個數(因為到達時必須停留一次) 然后發現子樹里不管怎么走,對該點的停留次數的影響都是$1$,所以每一個子樹里肯定要走出最優的方案 那么我們設$dp[v]$表示$v$這一整棵子樹的最優方案的權值,考慮從$u$點如何選擇才能使該點最優 首先自己必須選,然后把所有兒子的$dp$值排個序,取前$cnt[u]-1$個或一直取到第一個$dp$為0的值,不難發現沒有方案會比他更優 然后存兒子的$dp$值的話可以用vector 現在的問題就是怎么判斷方案是否唯一 首先,如果兒子的$dp$值的前$cnt[u]-1$個里有0,那么該點的最優方案肯定不唯一(因為0那個點可以選或不選) 其次,如果第$cnt[u]-1$和$cnt[u]$個都大于0且相等,那么方案也不唯一(因為這兩個都可以選) 然后如果子樹的方案不唯一,自己的方案也不唯一 所以用結構體存儲子樹的$dp$,分別記錄最大權值和方案是否唯一,不斷向上dp即可 交上去竟然1A了…… 1 //minamoto 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 5 char buf[1<<21],*p1=buf,*p2=buf; 6 inline int read(){ 7 #define num ch-'0' 8 char ch;bool flag=0;int res; 9 while(!isdigit(ch=getc())) 10 (ch=='-')&&(flag=true); 11 for(res=num;isdigit(ch=getc());res=res*10+num); 12 (flag)&&(res=-res); 13 #undef num 14 return res; 15 } 16 const int N=100005; 17 struct node{ 18 int v,f; 19 node(){} 20 node(int v,int f):v(v),f(f){} 21 inline node operator +(const node &b)const 22 {return node(v+b.v,f|b.f|(b.v==0));} 23 inline bool operator <(const node &b)const 24 {return v>b.v;} 25 inline bool operator ==(const node &b)const 26 {return v==b.v;} 27 inline void operator +=(const node &b) 28 {*this=*this+b;} 29 }dp[N]; 30 int head[N],Next[N<<1],ver[N<<1],tot; 31 inline void add(int u,int v){ 32 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 33 } 34 vector<node> val[N];int a[N],cnt[N],n,m; 35 void dfs(int u,int fa){ 36 for(int i=head[u];i;i=Next[i]){ 37 int v=ver[i];if(v==fa) continue; 38 dfs(v,u); 39 val[u].push_back(dp[v]); 40 } 41 dp[u]=node(a[u],0); 42 sort(val[u].begin(),val[u].end()); 43 int i=0,s=val[u].size(),k=cnt[u]-1; 44 for(;i<s&&i<k&&val[u][i].v>=0;++i) dp[u]+=val[u][i]; 45 if(i<s-1&&val[u][i].v>0&&val[u][i]==val[u][i+1]) dp[u].f=1; 46 } 47 int main(){ 48 // freopen("testdata.in","r",stdin); 49 n=read(); 50 for(int i=2;i<=n;++i) a[i]=read();a[1]=0; 51 for(int i=2;i<=n;++i) cnt[i]=read();cnt[1]=n+1; 52 for(int i=1,u,v;i<n;++i) 53 u=read(),v=read(),add(u,v),add(v,u); 54 dfs(1,0); 55 printf("%d\n",dp[1].v); 56 puts(dp[1].f?"solution is not unique":"solution is unique"); 57 return 0; 58 }
?
轉載于:https://www.cnblogs.com/bztMinamoto/p/9787004.html
總結
以上是生活随笔為你收集整理的bzoj4472: [Jsoi2015]salesman(树形dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 福布斯全球最佳雇主榜:网易排名80 大幅
 - 下一篇: 系统分析与设计结对项目———Wordco