您的位置:首页 > 其它

HDU 4313 Matrix

2014-05-16 03:05 549 查看
链接请戳-->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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图论 MST