题意
最小生成树
思路
Kruskal
代码
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N=1005;
const int M=N*N;
int num[N][N];
int father[M];
struct Edge{
int u,v,w;//本位,前位,两者间的距离
}edge[2*M];
int cmp(Edge a,Edge b){//不能省略
return a.w<b.w;
}
int find(int x){
if(x!=father[x]){//寻找已入集结点的父结点
father[x]=find(father[x]);
}
return father[x];
}
int Kruskal(int id){
sort(edge+1,edge+id,cmp);//将边从小到大排
int cost=0;
for(int i=1;i<id;i++){
int x=find(edge[i].u);
int y=find(edge[i].v);
if(x!=y){
father[x]=y;//入集
cost+=edge[i].w;
}
}
return cost;
}
int main(){
int t,n,m;
cin>>t;
for(int loop=1;loop<=t;loop++){
//cin>>n>>m;
//???cin时间超限,同学说因为scanf比较快……
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
father[i*m+j]=i*m+j;//未入集点初始化
//cin>>num[i][j];
scanf("%d",&num[i][j]);
}
}
int id=1;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int u=i*m+j;
if(i>0){
int v=(i-1)*m+j;
edge[id].u=u;
edge[id].v=v;
edge[id++].w=abs(num[i][j]-num[i-1][j]);//存储上边长度
}
if(j>0){
int v=i*m+j-1;
edge[id].u=u;
edge[id].v=v;
edge[id++].w=abs(num[i][j]-num[i][j-1]);//存储左边长度
}
}
}
int cost=Kruskal(id);
cout<<"Case #"<<loop<<":"<<endl;
cout<<cost<<endl;
}
return 0;
}