基環樹就是n個點n條邊的樹,每個點的入度為1就是外向基環樹因為這樣的話這個圖是往外擴張的,反之內向。
然後這個樹自然就隻且只有乙個環。
題意:n行m列,要求選n個守衛守衛n個行,m個守衛守衛m個列,守衛不能重複,且每個守衛只能守衛行或列,每個守衛乙個價值,求最小的代價。
思路:將關於點的圖轉化為關於邊的圖,構造乙個圖含有n+m個點表示n行和m列,題目給的圖上的每個點的價值就可以代表點到點的邊權了,可以想到如果要覆蓋所有的點,就是滿足條件的方案,這樣的話這個圖就是乙個每個點都是入度為1的基環樹,然後可以給邊從小到大排個序,通過並查集模擬生成乙個代價最小的外向基環樹就行了。對於基環樹,可以發現不在乎乙個邊所指的方向,只要選的邊所產生的點集構成的環滿足只有乙個就好了,所以只需要並查集判斷點所在的集合,開個huan用來判斷乙個點所在的集合是否產生了環,合併時對huan取並集就可以了。也可能乙個,而是幾個獨立的基環樹
#includeusingnamespace
std;
#define ll long long
const
int maxn=1e5+10
;int fa[2*maxn];
struct
note
e[2*maxn];
intcmp(note a,note b)
int huan[2*maxn];
int getf(int
x)int
main()
for(int i=1; i<=n+m; i++)
fa[i]=i;
sort(e+1,e+1+cnt,cmp);
ll ans=0
;
for(int i=1; i<=cnt; i++)
if(t1==t2&&huan[t1]==0
)
}printf(
"%lld
",ans);
}
BZOJ4883 棋盤上的守衛 最小基環樹
給乙個n m 1e5 n m leq1e5 n m 1e 5的棋盤,然後每個棋盤都可以放乙個守衛,你可以選擇是讓它保護橫向的也可以讓他保護縱向的。然後乙個位置最多只能放乙個守衛,放置在 i,j i,j i,j 這個位置的代價是wi,jw wi,j 然後求使得所有的位置都被守護的最小代價。完全不太會做...
有環的情況生成並查集
並查集最基本的查詢和合併就不多講了,直接看函式吧。合併過程中如果出現環,如5 6 7 5,那麼在找最終老大時會出現死迴圈,邊輸入每個節點的老大資訊邊合併可以有效的處理這種情況,具體解析看 注釋。include include include includeusing namespace std co...
並查集判斷環 並查集的路徑壓縮 和 帶秩優化
1.判斷環 參考部落格 思路 1.將用過的路徑連起來成為乙個集合,記錄下來 2.如果連通的兩個邊屬於乙個集合,那麼這個並查集就形成了乙個環 燈神 如果刪除2,4邊 可將2,4這條邊刪除測試 是否正確 如果刪除此邊則不會出現環記得將6改為5 initialise parent for int i 0 ...