HDU 4313 Matrix(贪心+并查集)

HDU 4313 Matrix(贪心+并查集)

分类:

HDU 4313

题意:

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

思路:

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

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

排序后枚举这些边:

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

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

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

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

ps.很不错的并查集详解:

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));elsemix(find(rd[i].u) , find(rd[i].v));}cout << ans << endl;}int main(){int t ; cin >> t;while(t–){input();solve();}return 0;}

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

上一篇HDU 4311&4312 Meeting point-1&2 (曼哈顿距离&&切比雪夫距离)

顶0踩0

世界没有永久的冬天;不要讨厌麻烦,

HDU 4313 Matrix(贪心+并查集)

相关文章:

你感兴趣的文章:

标签云: