HDU 4313 Matrix

来源:互联网 发布:视频音乐制作软件 编辑:程序博客网 时间:2024/04/28 03:02

链接请戳-->HDU 4313


题意:n个点,n-1条边,其中k个点每点有一个敌人,现在要毁坏一些边,使得两个敌人间不连通,要求毁掉边的权值总和最小值


思路

1.按权值从大到小排序;

2.对每条边,当两个点所含敌人总数不大于1时,这两个点可以加入同一集合,否则删掉它们所在的边;

(!关于为何从大到小排- -||,个人理解 : 如果从大到小,一般不会先删掉最大边,所以可使两个点连起来;如果从小到大排:权值小的边可能是需要删掉的边,但是却满足两边敌人数不大于1,用其充当边后,以后要删的就是权值比它大的边,这样求得的结果不是最小的)


以下代码

#include<stdio.h>#include<string.h>#include<string>#include<iostream>#include<algorithm>using namespace std;struct edges{    int u,v,w;}edge[100010];bool cmp( edges a, edges b ){    return a.w > b.w;}int n;int f[100010],enemy[100010];void set(){    for( int i = 0; i < n; ++i )        f[i] = i;}int find( int x ){    if( enemy[x]==1 ) enemy[f[x]] = enemy[x];    if( f[x]==x ) return x;    return f[x] = find(f[x]);}int main(){    int T;    int id,m;    scanf("%d",&T);    while( T-- )    {        scanf("%d%d",&n,&m);        set();        memset(edge,0,sizeof(edge));        memset(enemy,0,sizeof(enemy));        long long res = 0;        for( int i = 0; i < n-1; ++i )            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);        sort( edge,edge+n-1,cmp );        for( int i = 1; i <= m; ++i )        {            scanf("%d",&id);            enemy[id] = 1;        }        for( int i = 0; i < n-1; ++i )        {            int U = edge[i].u;            int V = edge[i].v;            int uu = find(U), vv = find(V);            if( enemy[uu]+enemy[vv]<=1 )            {                    f[uu] = vv;                    enemy[vv] = enemy[uu]+enemy[vv];            }            else res+=edge[i].w;        }        cout << res << endl;    }    return 0;}



0 0
原创粉丝点击