1. 程式人生 > >BZOJ 1601 [Usaco2008 Oct]灌水

BZOJ 1601 [Usaco2008 Oct]灌水

題目連結

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; }