1. 程式人生 > >bzoj 4472: [Jsoi2015]salesman

bzoj 4472: [Jsoi2015]salesman

註意 http n) opera str main AC int pty

4472: [Jsoi2015]salesman

鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=4472

Time Limit: 10 Sec Memory Limit: 128 MB

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

9
solution is unique
//最佳路線包括城鎮 1,2, 4, 5, 9。
題解:樹形dp, dp[i]表示i的子樹可獲得的最大利,dp[u] = sum(dp[v] ,dp[v] >= 0) 且只能選c[i] - 1個;要一個優先隊列就可以了, 註意判方案數重; 建雙向邊
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005; #define inf 10000008 int tot, head[maxn],dp[maxn],c[maxn]; int uni[maxn]; struct edge{ int v,nxt; }G[maxn * 2 +50]; struct ins{ int to, co; bool operator < (const ins &a)const{ return a.co > co; } }; priority_queue <ins> q[maxn]; void add(int u, int v){ G[++tot].nxt = head[u]; G[tot].v = v; head[u] = tot; } void dfs(int u, int fa){ for(int i = head[u]; i; i = G[i].nxt){ int v = G[i].v; if(v == fa)continue; dfs(v, u); q[u].push((ins){v,dp[v]}); } int tt = 0, last = -1; while(!q[u].empty() && tt < c[u]-1){ ins top = q[u].top(); if(top.co >= 0) { if(!top.co)uni[u] = 1; tt++; uni[u] = uni[u] | uni[top.to]; dp[u] += top.co; last = top.co; q[u].pop(); } else break; } if(!q[u].empty() && last != -1) if(q[u].top().co == last)uni[u] = 1; } int main(){ int n; scanf("%d",&n); for(int i = 2; i <= n; i++) scanf("%d",&dp[i]); c[1] = inf; for(int i = 2; i <= n; i++) scanf("%d",&c[i]); for(int i = 1; i < n; i++){ int u, v; scanf("%d%d",&u,&v); add(u, v); add(v, u); } dfs(1, 1); cout<<dp[1]<<endl; if(uni[1])cout<<"solution is not unique"<<endl; else cout<<"solution is unique"<<endl; }

bzoj 4472: [Jsoi2015]salesman