题意:n*m的矩阵,每个格子有一个值代表高度,现在需要灌溉所有的格子,管子的长度为高度差,求最小的管长之和;
思路:最小生成树kru算法,保存每个点到其左边和上边的点的高度差,比赛时想不到;
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int mm[1010][1010]; int fa[9000100]; int t,n,m,cnt; struct node{ int u,v; int len; bool operator <(const node& a)const{ return len<a.len; } }; node edge[5001000]; void init(){ for(int i=0;i<=n*m;i++){ fa[i]=i; } } int f(int x){ return x==fa[x]?x:fa[x]=f(fa[x]); } int combine(int a,int b){ int t1=f(a); int t2=f(b); if(t1!=t2){ fa[t1]=t2; return 1; } return 0; } int solve(){ int sum=0; init(); for(int i=0;i<cnt;i++){ if(combine(edge[i].u,edge[i].v)){ sum+=edge[i].len; } } return sum; } int main(){ int i,j,k,ans,pos,cas; scanf("%d",&t); for(cas=1;cas<=t;cas++){ scanf("%d%d",&n,&m); cnt=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ scanf("%d",&mm[i][j]); if(i>1){ edge[cnt].u=(i-1)*m+j; edge[cnt].v=(i-1)*m+j-m; edge[cnt++].len=abs(mm[i][j]-mm[i-1][j]); } if(j>1){ edge[cnt].u=(i-1)*m+j; edge[cnt].v=(i-1)*m+j-1; edge[cnt++].len=abs(mm[i][j]-mm[i][j-1]); } } } //cnt--; sort(edge,edge+cnt); printf("Case #%d:\n",cas); printf("%d\n",solve()); } return 0; }
时间: 2024-10-14 00:33:53