ybt高效高階3 2 2 新的開始

2021-10-18 16:43:20 字數 1363 閱讀 7447

有乙個圖,要你讓所有點所在的連通塊都至少有乙個標記點。

兩個點相連有乙個規定的費用,把乙個點標記也有費用。

要費用最小,輸出最小費用。

這道題看到判斷連通,我們就想到並查集。然後最小,就想到最小生成樹。

但是它不一定只選乙個點標記,而且如果標記了不止乙個點,整個圖就可以不是整個連通的。

那怎麼辦呢?

那我們想想如果標記了不止乙個點,那這些點之間會有怎樣的關係。

可以想到,它們之間是可以當做任意連通的,那你可以把每個標記的點之間都弄上一條邊,權值為 000。

但你如果要想最小生成樹那樣搞的話,就不能像上面那樣不停地加新的邊。

那我們考慮這樣弄:

我們把標記點也當做一條邊,權值就是標記的費用,然後從自己連向自己。

那然後你就把所有邊排序,像最小生成樹一樣搞。正常的邊就正常地搞。對於標記的邊我們分兩種:

第一種,第一次遇到標記的邊,那因為整個圖中一定要標記至少乙個,那我們是一定要標記這個點的。(因為你按費用從小到大排序,那你第乙個找到哦的標記的一定就是所有中權值最小的)

第二種,不止第一次,那它其實就相當於跟前面標記過的點連邊。那根據這樣的方法,前面的標記過的點一定是連通了的,那我們只要隨便選乙個就可以了。當然,如果已經連通,就沒有必要標記。

還有迴圈結束的條件就多了乙個,不止是正常的邊的數量要是 n−1

n-1n−

1,還要至少有乙個點被標記。

#include

#include

using

namespace std;

struct node a[

90001

+100001];

int n, now, num, last, fa[

301]

, line;

long

long ans;

bool

cmp(node x, node y)

intfind

(int now)

intmain()

now = n;

for(

int i =

1; i <= n; i++)}

}sort

(a +

1, a + now +

1, cmp)

;for

(int i =

1; i <= now; i++

)else

line++;if

(line == n -

1&& last)

break;}

}else

}printf

("%lld"

, ans)

;return0;

}

ybt 1488 新的開始

不難看出這是一道最小生成樹 but,我 蒟蒻 一開始以為是取最小的 v i v i v i 然後構建最小生成樹 這樣會有乙個問題,建造電網有時候不一定會比建造電站更優 so 我們可以把所有建電站的邊連到乙個虛點上,這樣直接進行最小生成樹就不會有問題了 include using namespace ...

ybt高效高階1 5 1 走迷宮

在乙個 n n 的地圖中,一些地方可以走一些不可以走。問你從乙個地方走到另乙個地方的最小步數。就是直接 bfs 搞過去。跑圖,跑到要的點就輸出退出。include include using namespace std int n,a 1001 1001 sx,sy,tx,ty,ans,now,no...

ybt高效高階2 4 1 字首統計

有一堆字串,然後每次有乙個詢問,問乙個有多少個字串是乙個給出的字串的字首。這道題可以看出用 trie 樹 甚至有點模板 就建樹就普通的建。至於詢問,其實我們可以按著長度推 trie 數的位置,每次長度都是乙個字首。然後答案加上就可以。當然,我們在詢問的時候已經不用再重新建樹,遇到沒有這個分支的就可以...