有乙個圖,要你讓所有點所在的連通塊都至少有乙個標記點。
兩個點相連有乙個規定的費用,把乙個點標記也有費用。
要費用最小,輸出最小費用。
這道題看到判斷連通,我們就想到並查集。然後最小,就想到最小生成樹。
但是它不一定只選乙個點標記,而且如果標記了不止乙個點,整個圖就可以不是整個連通的。
那怎麼辦呢?
那我們想想如果標記了不止乙個點,那這些點之間會有怎樣的關係。
可以想到,它們之間是可以當做任意連通的,那你可以把每個標記的點之間都弄上一條邊,權值為 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 數的位置,每次長度都是乙個字首。然後答案加上就可以。當然,我們在詢問的時候已經不用再重新建樹,遇到沒有這個分支的就可以...