HDU 4313 Matrix
2012-09-15 11:40
465 查看
题意: n个点的一棵树,其中有k个敌人所在结点,要破坏一些边使得这 k 个点互不可达,求出破坏边的最小权值和。
分析: 对于有n个结点的树,删除任意的k (k<=n-1)条边都能将原树分成k+1个部分
按照题意至少需要将原树划分成 k 个部分(此时每部分中都包含一个敌人的点),删除的边数为k-1。
类似kruskal最小生成树的过程,不过此处将边按权值从大到小排列,每次将边加进来时要判断是否会使两个危险的
点连通,是的话这条边就是需要被删除的,否则将它加到树上。
分析: 对于有n个结点的树,删除任意的k (k<=n-1)条边都能将原树分成k+1个部分
按照题意至少需要将原树划分成 k 个部分(此时每部分中都包含一个敌人的点),删除的边数为k-1。
类似kruskal最小生成树的过程,不过此处将边按权值从大到小排列,每次将边加进来时要判断是否会使两个危险的
点连通,是的话这条边就是需要被删除的,否则将它加到树上。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> using namespace std; #define maxn 100005 #define clr(x)memset(x,0,sizeof(x)) int n,m; int u[maxn],v[maxn],w[maxn]; int r[maxn],f[maxn]; int find(int x) { return f[x]==x?x:(f[x]=find(f[x])); } void join(int x,int y) { int fx=find(x); int fy=find(y); if(fx!=fy) { if(fx<fy) f[fy]=fx; else f[fx]=fy; } } bool cmp(int a,int b) { return w[a]>w[b]; } int pos[maxn]; __int64 kruskal() { int i; __int64 res=0; for(i=0;i<n;i++) f[i]=i; for(i=0;i<n-1;i++) r[i]=i; sort(r,r+n-1,cmp); for(i=0;i<n-1;i++) { int e=r[i]; int fx=find(u[e]); int fy=find(v[e]); if(pos[fx]&&pos[fy]) { res+=w[e]; continue; } if(pos[fx]||pos[fy]) pos[fx]=pos[fy]=1; join(fx,fy); } return res; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); int i,a,b,c; for(i=0;i<n-1;i++) { scanf("%d%d%d",&a,&b,&c); u[i]=a; v[i]=b; w[i]=c; } clr(pos); for(i=0;i<m;i++) { int tmp; scanf("%d",&tmp); pos[tmp]=1; } printf("%I64d\n",kruskal()); } return 0; }
相关文章推荐
- HDU 4313 Matrix (贪心)
- hdu - 4313 - Matrix - 树形dp 或者 贪心
- HDU 4313 Matrix
- HDU-4313-Matrix
- hdu 4313 Matrix(树形DP)
- HDU 4313 Matrix (贪心+并查集)
- hdu 4313 Matrix(最大生成树)
- HDU 4313 Matrix
- hdu 4313 Matrix 并查集 多校联合赛(二) 第四题
- hdu 4313 - Matrix(最小生成树,并查集)
- hdu 4313 Matrix (最小生成树krusual)
- HDU 4313 Matrix(并查集/破坏边使得k个点两两不连通的最少代价)
- HDU 4313 Matrix
- HDU 4313 Matrix 树形dp
- HDU 4313 Matrix(并查集)
- 并查集--HDU - 4313 Matrix
- hdu 4313 Matrix(并查集)
- HDU 4313 Matrix (最小生成树)
- hdu 4313 Matrix 树形dp
- hdu 4313 Matrix