jzoj 2936_逐個擊破_並查集
阿新 • • 發佈:2017-09-08
數組a printf i++ ace name 遇到 getchar() get ()
題目描述
三大戰役的平津戰場上,傅作義集團在以北平、天津為中心,東起唐山西至張家口的鐵路線上擺起子一字長蛇陣,並企圖在潰敗時從海上南逃或向西逃竄。為了就地殲敵不讓其逃走,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]; } inlineint 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_逐個擊破_並查集