hdu 4313(kruskal思想)

来源:互联网 发布:2017淘宝排名突然下降 编辑:程序博客网 时间:2024/06/07 18:20

对于有n个结点的树,容易证明删除任意的k (k<=n-1)条边都能将原树切成k+1个部分。按照题意至少需要将原树划分成d个部分(此时每部分中都包含一个危险的点),删除的边数为d-1。

贪心算法:类似kruskal最小生成树的过程,不过此处将边按权值从大到小排列,每次将边加进来时要判断是否会使两个危险的点连通,是的话这条边就是需要被删除的,否则将它加到树上。

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int ac[110000],father[110000];__int64 sum;struct hello{int x,y,z;}yi[110000];bool cmp(hello t1,hello t2){return t1.z>t2.z;}int find(int x){if(x!=father[x])father[x]=find(father[x]);return father[x];}void add(int x,int y,int z){x=find(x);y=find(y);if(ac[x]&&ac[y])return ;else{if(ac[x]){father[y]=x;}elsefather[x]=y;sum+=z;}}int main(){int a,b,n,m,ncase,i;scanf("%d",&ncase);while(ncase--){__int64 max=0;sum=0;scanf("%d%d",&n,&m);memset(ac,0,sizeof(ac));for(a=0;a<=n;a++)father[a]=a;for(a=0;a<n-1;a++){scanf("%d%d%d",&yi[a].x,&yi[a].y,&yi[a].z);max+= yi[a].z;}for(a=0;a<m;a++){scanf("%d",&b);ac[b]=1;}sort(yi,yi+n-1,cmp);for(a=0;a<n-1;a++)add(yi[a].x,yi[a].y,yi[a].z);printf("%I64d\n",max-sum);}}


原创粉丝点击