题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=1601

题解

在一块土地上建造水库,相当于从一个有水的0号水库引水,做一遍最小生成树即可。

代码

#include <cstdio>
#include <algorithm>

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

const int maxn=300;
const int maxm=50000;

struct edge
{
  int x,y,l;

  edge(int _x=0,int _y=0,int _l=0):x(_x),y(_y),l(_l){}

  bool operator <(const edge &other) const
  {
    return l<other.l;
  }
};

edge e[maxm+10];
int n,m,ans;

namespace dsu
{
  int fa[maxn+10];

  int clear()
  {
    for(int i=0; i<=n; ++i)
      {
        fa[i]=i;
      }
    return 0;
  }

  int find(int x)
  {
    return (fa[x]==x)?x:(fa[x]=find(fa[x]));
  }
};

int main()
{
  n=read();
  for(int i=1; i<=n; ++i)
    {
      int x=read();
      e[++m]=edge(0,i,x);
    }
  for(int i=1; i<=n; ++i)
    {
      for(int j=1; j<i; ++j)
        {
          int x=read();
          e[++m]=edge(i,j,x);
        }
      for(int j=i; j<=n; ++j)
        {
          read();
        }
    }
  std::sort(e+1,e+m+1);
  dsu::clear();
  for(int i=1,cnt=0; cnt<n; ++i)
    {
      int x=dsu::find(e[i].x),y=dsu::find(e[i].y);
      if(dsu::fa[x]!=dsu::fa[y])
        {
          dsu::fa[x]=y;
          ++cnt;
          ans+=e[i].l;
        }
    }
  printf("%d\n",ans);
  return 0;
}