NC229893. 点权
描述
输入描述
第一行,一个正整数 表示点数。接下来 行,每行三个正整数 ,表示 和 之间有一条权值为 的边连接。()对于 的数据,。
输出描述
一行 个整数,第 个数表示让 号节点的点权变为 的最小消耗。
示例1
输入:
5 1 2 1 1 3 2 2 4 3 2 5 4
输出:
10 7 0 0 0
示例2
输入:
6 1 2 3 2 3 4 3 4 5 4 5 1 4 6 2
输出:
0 -1 -1 3 0 0
C++ 解法, 执行用时: 94ms, 内存消耗: 10900K, 提交时间: 2021-12-10 22:41:35
#include<bits/stdc++.h> using namespace std; int i,j,k,n,m,t,a[200500],f[200500],w,b[200500]; bool vis[200500]; vector<pair<int,int> > v[200500]; int main(){ ios::sync_with_stdio(0); priority_queue<pair<int,int> >q; cin>>n; if(n==1){cout<<0;return 0;} for(i=1;i<n;i++){ cin>>j>>k>>w; v[j].push_back({k,w}); v[k].push_back({j,w}); a[j]++;a[k]++; } for(i=1;i<=n;i++){ if(a[i]==1){ vis[i]=1; for(auto [j,k]:v[i]){if(vis[j]){continue;}q.push({-k,j});} } } while(!q.empty()){ auto [x,y]=q.top();q.pop(); if(vis[y])continue; x=-x;f[y]+=x;b[y]++; if(b[y]==2){ vis[y]=1; for(auto [i,j]:v[y]){if(vis[i]){continue;}q.push({-f[y]-j,i});} } } for(i=1;i<=n;i++)cout<<(((!vis[i])?-1:f[i]))<<' '; }