1. 程式人生 > >jzoj 2936_逐個擊破_並查集

jzoj 2936_逐個擊破_並查集

數組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];
}
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_逐個擊破_並查集