1 条题解
-
0
贪心+树剖?
从根节点开始看,如果我们选一个节点的话,肯定选一条从根节点出发往下,权值和最大的路径。
如果再选一个节点的话,候选解为:所有没被计算过的根节点的儿子,往下的权值和最大的路径、第一次选过的链的所有“分支节点”往下的权值和最大的路径。
然后第二次选择我们肯定是从这里面选一个最大的。后续贪心同理。
这一步的代码是:
const int N = 5e6+10; vector<vector<int>> g; int a[N],son[N],val[N]; int p[N]; int n,m; void dfs1(int u,int fa){ son[u] = -1; for(auto v:g[u]){ if(v == fa) continue; dfs1(v,u); if(son[u] == -1|| val[v] > val[son[u]]) son[u] = v,val[u] = val[v]; } val[u] += a[u]; } ll ans = 0; void solve(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; g = vector<vector<int>>(n+1); for(int i=2;i<=n;i++) cin>>p[i],g[p[i]].push_back(i); dfs1(1,-1); priority_queue<pii> pq; auto dfs2 = [&](auto &&dfs2,int u)->void{ for(auto v:g[u]){ if(v!=son[u]){ pq.push({val[v],v}); } } if(son[u]!=-1){ dfs2(dfs2,son[u]); } }; pq.push({val[1],1}); while(pq.size() && m ){ auto [v,u] = pq.top(); pq.pop(); m--; ans += v; dfs2(dfs2,u); } cout<<ans<<endl; }
但是常数太大T了。 考虑一下可以不用优先队列,直接先处理出解空间中的路径,根据路径和sort一下取最大的m个即可。
#include<bits/stdc++.h> #define endl '\n' using namespace std; using ll = long long; using pii = pair<int,int>; using pll = pair<ll,ll>; const int N = 5e6+10; //vector<vector<int>> g; int read() { int x = 0, w = 1; char ch = 0; while (ch < '0' || ch > '9') { // ch 不是数字时 if (ch == '-') w = -1; // 判断是否为负 ch = getchar(); // 继续读入 } while (ch >= '0' && ch <= '9') { // ch 是数字时 x = x * 10 + (ch - '0'); // 将新读入的数字「加」在 x 的后面 // x 是 int 类型,char 类型的 ch 和 '0' 会被自动转为其对应的 // ASCII 码,相当于将 ch 转化为对应数字 // 此处也可以使用 (x<<3)+(x<<1) 的写法来代替 x*10 ch = getchar(); // 继续读入 } return x * w; // 数字 * 正负号 = 实际数值 } int h[N],e[N],ne[N],idx; void add(int a,int b){ e[idx] = b,ne[idx] = h[a],h[a] = idx++; } int a[N],son[N],val[N]; int p[N]; int n,m; void dfs1(int u,int fa){ son[u] = -1; for(int i = h[u];i!=-1;i = ne[i]){ int v = e[i]; if(v == fa) continue; dfs1(v,u); if(son[u] == -1|| val[v] > val[son[u]]) son[u] = v,val[u] = val[v]; } val[u] += a[u]; } ll ans = 0; vector<int> path; void dfs2(int u,int fa,bool flag){ if(flag) path.emplace_back(val[u]); for(int i = h[u];i!=-1;i=ne[i]){ int v = e[i]; if(v == son[u]){ dfs2(v,u,false); }else{ dfs2(v,u,true); } } } void solve(){ n = read(),m = read(); memset(h,-1,sizeof h); for(int i=1;i<=n;i++) a[i] = read(); //g = vector<vector<int>>(n+1); for(int i=2;i<=n;i++) p[i] = read(),add(p[i],i); dfs1(1,-1); dfs2(1,-1,true); sort(path.begin(),path.end(),greater<int>()); m = min(m,(int)path.size()); for(int i = 0;i<m;i++){ ans += path[i]; } cout<<ans<<endl; } int main(){ ifstream test_file("0in.txt"); if (test_file) { freopen("0in.txt", "r", stdin); freopen("0output.txt", "w", stdout); } std::ios::sync_with_stdio(0);std::cout.tie(0);std::cin.tie(0); int T = 1; #ifdef MULTI_TEST cin>>T; #endif while(T--){ solve(); } return 0; }
- 1
信息
- ID
- 250
- 时间
- 4000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- 递交数
- 23
- 已通过
- 4
- 上传者