HDU 4313 Contest 2
2024-09-29 03:50:33
很明显的树形DP了。但网上有的说可以用并查集。。。。
考虑一棵子树,当根结点有机器人时,则必定所有子树都要和根结点断开,而根结点向上返回的路径值则为其父结点与根结点连边的权值。
当根结点安全时,假设其子树有K个危险结点,而由于K个结点需要两两不能相连,那么,至少断开K-1个结点。则把权值最小的K-1断开即可。而剩下的那个结点与根结点的边权值则返上至上一层。这时,相当于K-1个结点都从树中剪去,变成了一条单路径的树了吧,则若要断开剩下的结点与其他点的通路(假设要与祖父结点断开),则必定是要断开剩下结点与祖父结点该路径上权值最小的边。于是,返回的便是最小权值的边。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define N 100005
using namespace std; struct Edge{
int u,v;
int cost,next;
}edge[N*2];
int head[N],tot;
__int64 ans;
bool mech[N]; void addedge(int u,int v,int c){
edge[tot].u=u;
edge[tot].v=v;
edge[tot].cost=c;
edge[tot].next=head[u];
head[u]=tot++;
} int dfs(int now,int parent,__int64 parval){
__int64 maxi=0;__int64 sum=0,tmp;
for(int e=head[now];e!=-1;e=edge[e].next){
if(parent==edge[e].v) continue;
tmp=dfs(edge[e].v,now,edge[e].cost);
maxi=max(maxi,tmp);
sum+=tmp;
}
if(!mech[now])
ans+=(__int64)(sum-maxi);
else ans+=(__int64)sum;
if(mech[now])
return parval;
return min(parval,maxi);
} int main(){
int T,n,k,u,v,c;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
memset(head,-1,sizeof(int)*(n+1));
memset(mech,false,sizeof(bool)*(n+1));
tot=0;
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c);
addedge(v,u,c);
}
for(int i=1;i<=k;i++){
scanf("%d",&u);
mech[u]=true;
}
ans=0;
dfs(0,-1,0);
printf("%I64d\n",ans);
}
return 0;
}
最新文章
- Xdebug文档(三)堆栈跟踪
- 提交留言HTML模板代码
- Windows 10一周年更新正式版官方ISO镜像(1607)
- myEclipse 界面窗口打不开问题
- GIT 在本地保存账户和密码
- Codeforces Round #287 (Div. 2) C. Guess Your Way Out! 思路
- iOS - UIControl
- 在腾讯云上创建您的SQL Cluster(2)
- css选择器浏览器支持情况
- 【转】Eclipse中一键调用javah生成jni的头文件
- 【转载】hadoop的版本问题
- size_t为何这么重要?
- phpcms v9中模板标签使用及联动菜单
- HTML学习(四)样式
- 操作系统之cache、伙伴系统、内存碎片、段式页式存储管理
- CF #244 D. Match &; Catch 后缀数组
- nodejs 开启debug选项问题
- 常见类——Object
- Android 开发者必知必会的权限管理知识
- smarty 循环一维关联数组