1. 程式人生 > 其它 >P1550 [USACO08OCT]Watering Hole G 最小生成樹+

P1550 [USACO08OCT]Watering Hole G 最小生成樹+

Farmer John 的農場缺水了。

他決定將水引入到他的nn個牧場。他準備通過挖若干井,並在各塊田中修築水道來連通各塊田地以供水。在第ii號田中挖一口井需要花費W_iWi元。連線ii號田與jj號田需要P_{i,j}Pi,jP_{j,i}=P_{i,j}Pj,i=Pi,j)元。

請求出 FJ 需要為使所有農場都與有水的農場相連或擁有水井所需要的最少錢數。

--

正解是類似於開一個超級原點這樣的東西作為水井費用

評論區yy了可以在維護並查集的時候判斷是分開挖好還是一起挖好。

我yy了一個在找出最小生成樹後遍歷一遍dfs,如果在當前集合建水井的費用小於和父節點連的邊,就在當前集合建..

懶狗想建超級原點

#include<bits/stdc++.h>
using namespace std;
int parent[50001],n,w[50005];
int find(int x)
{
   if(parent[x]!=x)
    {
        parent[x]=find(parent[x]);
    }
    return parent[x];
} 
struct node
{
    int from,to,d;
    bool operator < (const node&a) const
    {
        return d<a.d;
    }
}g[
1000000]; int main( ) { int cnt=0; cin>>n; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { int dis; cin>>dis; if(i==j) continue; cnt++; g[cnt].d=dis;g[cnt].from=i;g[cnt].to=j; }
for(int i=1;i<=n;i++) {cnt++; g[cnt].d=w[i]; g[cnt].from=i; g[cnt].to=n+1; } sort(g+1,g+cnt+1); for(int i=1;i<=n+1;i++) { parent[i]=i; } int ans=0; for(int i=1;i<=cnt;i++) { int fa=find(g[i].from),fb=find(g[i].to); if(fa!=fb) { parent[fa]=parent[fb]; ans+=g[i].d; } } cout<<ans; }