P1550 [USACO08OCT]Watering Hole G 最小生成树+
Farmer John 的农场缺水了。
他决定将水引入到他的 nn 个牧场。他准备通过挖若干井,并在各块田中修筑水道来连通各块田地以供水。在第 ii 号田中挖一口井需要花费 W_iWi 元。连接 ii 号田与 jj 号田需要 P_{i,j}Pi,j(P_{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; }
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号