Codeforces Round #646 (Div. 2) 参与排名人数14203
[codeforces 1363E] Tree Shuffling 可以回避排序的树上结构(链式结构不超时的写法)
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址http://codeforces.com/contest/1363/problem/E
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
E - Tree Shuffling | GNU C++17 | Accepted | 342 ms | 17200 KB |
思路:
数据传入,采用自顶向下的方式,数据处理,采用自底向上的方式。此种方式,在此题中,可避免单独写排序算法,可避免单独写更新算法,有效的避免了链式结构的超时,也是该题编写过程中的精妙之处。
看懂该题代码,需要具备的知识是,熟练掌握子树节点数量计算对应的算法。
AC代码如下
#include <cstdio>
#include <algorithm>
#define maxn 200010
#define LL long long
#define INF 1000000010
using namespace std;
int a[maxn],b[maxn],c[maxn],f[maxn],g[maxn],head[maxn],tot,n;
LL ans;
struct node{
int to,next;
}e[maxn<<1];
void add_edge(int u,int v){//邻接表
tot++,e[tot].to=v,e[tot].next=head[u],head[u]=tot;
}
void init(){
int i,u,v;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(i=1;i<n;i++)scanf("%d%d",&u,&v),add_edge(u,v),add_edge(v,u);
}
void dfs(int u,int fa,int cost){//注意:数据的传入是自顶向下
int p,v;
cost=min(cost,a[u]);//此步很神奇,避免了排序代码
if(b[u]==0&&c[u]==1)f[u]=1;
if(b[u]==1&&c[u]==0)g[u]=1;
for(p=head[u];p;p=e[p].next){
v=e[p].to;
if(v==fa)continue;
dfs(v,u,cost);
f[u]+=f[v];
g[u]+=g[v];
}
int num=min(f[u],g[u]);
ans+=(LL)cost*num*2;//注意,数据的处理是自底向上
f[u]-=num,g[u]-=num;//此步很神奇,避免了单独再写的更新代码
}
void solve(){
if(f[1]||g[1]){printf("-1\n");return;}//匹配未成功
printf("%lld\n",ans);
}
int main(){
init();
dfs(1,0,INF);
solve();
return 0;
}