jzoj 2936_逐个击破_并查集
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj 2936_逐个击破_并查集相关的知识,希望对你有一定的参考价值。
题目描述
三大战役的平津战场上,傅作义集团在以北平、天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜。为了就地歼敌不让其逃走,maozedong制定了先切断敌人东洒两头退路然后再逐个歼灭敌人的战略方针。
秉承伟大军事家的战略思想,作为一个有智慧的军长你,遇到了一个类似的战场局面:
现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K个地方军团互相隔离开,以便第二步逐个击破敌人。
思路
最大生成树,可以用一个数组a来判断每一个并查集里面有几个是被占领的城市,在合并集合时转移即可
#include <stdio.h> #include <algorithm> using namespace std; #define maxn 100005 struct edge { int x, y, w; }e[maxn]; int f[maxn], a[maxn]; int cmp(edge a, edge b) { return a.w > b.w; } int find(int x) { if (f[x] == x) return x; f[x] = find(f[x]); return f[x]; } inline int read() { int x=0,p=1;char ch=getchar(); while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘)p=-1;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*p; } int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) f[i] = i; for (int i = 1; i <= m; i++) { int x = read(); a[x] = 1; } double ans = 0; for (int i = 1; i < n; i++) { int x, y, w; scanf("%d%d%d", &x, &y, &w); e[i] = (edge) {x, y, w}; ans += w; } sort(e + 1, e + n, cmp); for (int i = 1; i < n; i++) { int xx = find(e[i].x), yy = find(e[i].y); if (a[xx] + a[yy] < 2) { f[xx] = yy; a[yy] += a[xx]; a[xx] = 0; ans -= e[i].w; } } printf("%.lf\n", ans); }
以上是关于jzoj 2936_逐个击破_并查集的主要内容,如果未能解决你的问题,请参考以下文章