\(n\) 个牧场,需要引水灌溉,第 \(i\) 号牧场挖井需要 \(w_i\),连接 \(i,j\) 的管道需要 \(p_{i,j}\),求对所有牧场实施灌溉的最小代价方案。\(n \leq 300\)

Solution

难度:L2

设虚点 \(n+1\) 表示井水,然后连接所有边跑最小生成树即可

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 305;
int n,w[N],p[N][N],fa[N],ind;

struct edge {
    int u,v,w;
    bool operator < (const edge &b) {
        return w<b.w;
    }
} e[N*N*2];

int find(int p) {
    return fa[p]==p?p:fa[p]=find(fa[p]);
}
void merge(int p,int q) {
    p=find(p); q=find(q);
    if(p!=q) fa[p]=q;
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n+1;i++) fa[i]=i;
    for(int i=1;i<=n;i++) cin>>w[i];
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            cin>>p[i][j];
        }
    }
    for(int i=1;i<=n;i++) e[++ind]={n+1,i,w[i]};
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            if(i==j) continue;
            e[++ind]={i,j,p[i][j]};
        }
    }
    sort(e+1,e+ind+1);
    int ans=0;
    for(int i=1;i<=ind;i++) {
        edge &ed=e[i];
        if(find(ed.u)!=find(ed.v)) {
            ans+=ed.w;
            merge(ed.u,ed.v);
        }
    }
    cout<<ans;
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-01-30
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-31
  • 2022-12-23
猜你喜欢
  • 2021-09-19
  • 2022-12-23
  • 2021-09-01
  • 2022-01-01
  • 2021-07-09
  • 2021-12-16
相关资源
相似解决方案