洛谷U4807抽水机[最小生成树]

时间:2021-09-15 23:26:37

题目背景

kkk被Farmer John和他的奶牛贝茜虐的很惨,然后她也想体验下一个Farmer的生活。但她又懒得种地,就选择养鱼。

题目描述

这些鱼都是热带鱼(废话),很娇贵(比kkk娇贵),要经常换水,要不然每当kkk走过来的时候鱼们就会一起使劲拍尾巴导致kkk并不情愿的洗个冷水澡(别问我热带鱼为毛这么机智)。但kkk并不勤快,他只想花费最少的力气以实现换水。

kkk的鱼塘可以分成n*n个独立小池,每两个相邻的小池间都有一个水闸控制水位。开启一个水闸需要花费的力气是这两个相邻的小池的水位之差。已知各个小池的水位,kkk想知道她要给每个小池都换水至少需要多少力气。

输入输出格式

输入格式:

第一行一个整数n

接下来n*n个数表示各个小池的水位

输出格式:

最小力气

输入输出样例

输入样例#1:
3
1 2 3
4 5 6
7 8 9
输出样例#1:
12

说明

1<=n<=100

1<=水位<=100


题目不清楚,水闸同时打开,要不然还得考虑连通器原理

裸的最小生成树

注意数组开多大,因为这个WA好几次,最后只有81分了,导致比赛与第一无缘

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x;
}
int n,m,a[N][N];
inline int id(int i,int j){return (i-)*n+j;}
struct edge{
int u,v,w;
bool operator <(const edge &rhs)const{return w<rhs.w;}
}e[N*(N-)*];
int cnt=;
inline void ins(int u,int v,int w){
cnt++;
e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
}
int fa[N*N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
long long kruskal(){
n*=n;
sort(e+,e++cnt);
long long ans=,num=;
for(int i=;i<=n;i++) fa[i]=i;
for(int i=;i<=cnt;i++){
int u=e[i].u,v=e[i].v;
int x=find(u),y=find(v);
if(x!=y){
ans+=e[i].w;
fa[x]=y;
if(++num==n-) break;
}
}
return ans;
}
int main(){
n=read();
m=*n*(n-);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
a[i][j]=read();
//a[i][j]=i+j;
if(j!=) ins(id(i,j),id(i,j-),abs(a[i][j]-a[i][j-]) );
if(i!=) ins(id(i,j),id(i-,j),abs(a[i][j]-a[i-][j]) );
}
cout<<kruskal();
//printf("%d %d",m,cnt);
}