HDU 4313 Matrix(贪心+并查集)

HDU 4313

题意:

有n个节点,n-1条边,其中k个节点为危险节点,有大规模杀伤性武器,切断哪些路能使得这些大规模杀伤性武器的危险节点之间彼此不连通,且切断的边权值之和最小。

思路:

初始化每个节点为一个集合,并记录每个集合中危险节点的数目(0或1)。

要实现权值之和尽可能的小,则要权值尽可能小,故先将n-1条边按权值先升序排序。

排序后枚举这些边:

若边的两端节点所在集合均有大规模杀伤性武器,则删除它并累计其权值。

若只有一边有,则合并这两个集合(用并查集),合并时尽可能将危险节点置于父节点位置。

若没有,则合并这两个集合。

枚举结束,输出权值累计值即可。

ps.很不错的并查集详解:http://blog.csdn.net/dellaserss/article/details/7724401

code:

/*
* @author Novicer
* language : C++/C
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
#define INF 2147483647
#define cls(x) memset(x,0,sizeof(x))
#define rise(i,a,b) for(int i = a ; i <= b ; i++)
using namespace std;
const double eps(1e-8);
typedef long long lint;

const int maxn = 100000 + 5;
struct Edge{
	int u , v , c;
}rd[maxn];
int n,k;
int flag[maxn];
int father[maxn];

bool cmp(Edge a , Edge b){
	return a.c > b.c;
}

void init(){
	cls(flag);
	for(int i = 0 ; i < maxn ; i++){
		father[i] = i;
	}
}

int find(int x){
	if(x != father[x]){
		father[x] = find(father[x]);
	}
	return father[x];
}

void mix(int x ,int y){
	father[x] = y;
}

void input(){
	init();
	cin >> n >> k;
	for(int i = 0 ; i < n-1 ; i++){
		scanf("%d%d%d",&rd[i].u,&rd[i].v,&rd[i].c);
	}
	for(int i = 0 ; i < k ; i++){
		int tmp;
		scanf("%d",&tmp);
		flag[tmp] = 1;
	}
}

void solve(){
	sort(rd , rd+n-1 , cmp);
	lint ans = 0 ;
	for(int i = 0 ; i < n-1 ; i++){
		if(flag[find(rd[i].u)] && flag[find(rd[i].v)])
			ans += rd[i].c;
		else if(flag[find(rd[i].u)])
			mix(find(rd[i].v) , find(rd[i].u));
		else
			mix(find(rd[i].u) , find(rd[i].v));
	}
	cout << ans << endl;
}
int main(){
	int t ; cin >> t;
	while(t--)	{
		input();
		solve();
	}
	return 0;
}

版权声明:博主表示授权一切转载:)

时间: 2024-12-21 13:45:00

HDU 4313 Matrix(贪心+并查集)的相关文章

HDU 4313 Matrix(并查集|最小生成树变种)

 题意:给你一个有n(2<=n<=100000)个节点的树,树中每条边都有一个权值.然后再给你k(2<=k<=n)个点,表示这些点上有一个机器人.最后让你删去一些边使任意两个机器人都不能互达,且所删边的权值之和要最小. 思路:不难发现,最后一定要正好去掉k-1条边才能使他们互不连通,对于这k-1条边我们希望他们的权值之和最小, 更进一步,我们希望选取的每条边都尽量小. 正常来想,应该是边权递增排序,每次去掉一条边,看是否不连通的数目加一,但这样做太麻烦. 可以反向来想,把边递减

hdu 3234 Exclusive-OR (并查集+异或性质)

Exclusive-OR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2177    Accepted Submission(s): 603 Problem Description You are not given n non-negative integers X0, X1, ..., Xn-1 less than 220 ,

HDU 4496 D-City (并查集)

题意:给你n个点m条边,问删除前i条边后有多少个连通分块. 思路:从后往前操作,从后往前添加i条边等于添加完m条边后删掉前m-i条边,可知刚开始没有边,所以sum[m]=n; #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #define M 100010

贪心 + 并查集 之 CODE[VS] 1069 关押罪犯 2010年NOIP全国联赛提高组

/* 贪心 + 并查集 之 CODE[VS] 1069 关押罪犯  2010年NOIP全国联赛提高组 两座监狱,M组罪犯冲突,目标:第一个冲突事件的影响力最小. 依据冲突大小,将M组罪犯按从大到小排序,按照排序结果,依次把每组罪犯分开放入两个监狱, 直到当前这组罪犯已经在同一个监狱中了,此时即为答案. 实现: 1)通过不在同一个监狱的罪犯,推断出在同一个监狱的罪犯.(依据:一共就两个监狱)      ftr[b] = a+n   // a和b是在不同监狱 ftr[c] = a+n   // a和

hdu 1811Rank of Tetris (并查集 + 拓扑排序)

1 /* 2 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B. 3 4 现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK". 5 否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出&quo

poj 1456 Supermarket (贪心+并查集)

# include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int fa[10010]; struct node { int p; int d; }; struct node a[10010]; bool cmp(node a1,node a2)//利润从大到小 { return a1.p>a2.p; } int find(int x) { if(fa[x]

Codeforces 437D The Child and Zoo(贪心+并查集)

题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去参观动物园,动物园分很多个区,每个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路的权值为该条路连接的两个区中权值较小的一个.如果两个区没有直接连接,那么f值即为从一个区走到另一个区中所经过的路中权值最小的值做为权值.问,平均两个区之间移动的权值为多少. 解题思路:并查集+贪心.将所有的边按照权值排序,从最大的开始连接,每次连接时计算的次数为连接两块的节点数的积(乘法原理). #in

HDU 1232 畅通工程(并查集)

畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 30485    Accepted Submission(s): 16013 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通(但不一定有

HDU 2017 Code Lock (并查集的应用+快速幂)

链接:HDU 3461 题目大意: 题目的大意是一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限次的"增加"操作后可以变成另一组密码,那么我们认为这两组密码是相同的.该题的目标就是在给定N.M和M个区间的前提下计算有多少种不同的密码. 根据题意,如果一个可调整的区间都没有的话,答案应该是26