您的位置:首页 > 其它

2015百度之星 初赛2 连接的管道 最小生成树

2015-05-31 22:00 274 查看
题意:老 Jack 有一片农田,以往几年都是靠天吃饭的。但是今年老天格外的不开眼,大旱。所以老 Jack 决定用管道将他的所有相邻的农田全部都串联起来,这样他就可以从远处引水过来进行灌溉了。当老
Jack 买完所有铺设在每块农田内部的管道的时候,老 Jack 遇到了新的难题,因为每一块农田的地势高度都不同,所以要想将两块农田的管道链接,老 Jack 就需要额外再购进跟这两块农田高度差相等长度的管道。

现在给出老 Jack农田的数据,你需要告诉老 Jack 在保证所有农田全部可连通灌溉的情况下,最少还需要再购进多长的管道。另外,每块农田都是方形等大的,一块农田只能跟它上下左右四块相邻的农田相连通。

思路: 建图,边权值是两点高度之差的绝对值。最小生成树,跑一发克鲁斯卡尔就行了。这题容易爆内存...建图的时候可以只加入单向边以节省空间。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdlib>
#include <map>
using namespace std;
#define I64_MAX 9223372036854775807
typedef long long ll;
const double pi=acos (-1.0);
const double eps=1e-8 ;
//const ll INF=(I64_MAX)/2;
//#pragma comment(linker, "/STACK:102400000,102400000")
const int inf=0x3f3f3f3f ;
#define maxx(a) memset(a, 0x3f, sizeof(a))
#define zero(a) memset(a, 0, sizeof(a))
#define FILL(a,b) memset(a, b, sizeof(a))
#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)
#define srep(i,n) for(i = 1;i <= n;i ++)
#define snuke(c,itr) for( __typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define mp make_pair
#define fi first
#define se second
typedef pair <int, int> pii;
typedef pair <ll, ll> PX;
typedef pair<int,ll> PIL;

const int MAXN=1000006;//最大点数
const int MAXM=2000006;//最大边数
int F[MAXN];//并查集使用
struct Edge
{
int u,v,w;
}edge[MAXM];//存储边的信息,包括起点/终点/权值
int tol;//边数,加边前赋值为0
void addedge(int u,int v,int w)
{

edge[tol].u=u;
edge[tol].v=v;
edge[tol++].w=w;
}
bool cmp(Edge a,Edge b)
{	//排序函数,讲边按照权值从小到大排序
return a.w<b.w;
}
int find(int x)
{
if(F[x]==-1)return x;
else return F[x]=find(F[x]);
}
int Kruskal(int n)//传入点数,返回最小生成树的权值,如果不连通返回-1
{
memset(F,-1,sizeof(F));
sort(edge,edge+tol,cmp);
int cnt=0;//计算加入的边数
int ans=0;
for(int i=0;i<tol;i++)
{
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2)
{
ans+=w;
F[t1]=t2;
cnt++;
}
if(cnt==n-1)break;
}
if(cnt<n-1)
return -1;//不连通
else
return ans;
}
const int maxn = 1005;
int mark[2][maxn];
pii d[2];
int n,m;
inline int cal(int x,int y){
return x*m+y;
}

int main(){
int T;
scanf("%d",&T);
d[0] = mp(0,-1);
d[1] = mp(-1,0);
for(int t=1;t<=T;t++){
scanf("%d%d",&n,&m);
tol = 0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&mark[i%2][j]);
for(int k=0;k<2;k++){
int x = i+d[k].fi;
int y = j+d[k].se;
if(x < 0 || y<0){
continue;
}
int v = abs(mark[i%2][j] - mark[x%2][y]);
//	printf("%d %d\n",mark[i%2][j],mark[x%2][y]);
int u1,u2;
u1 = cal(i,j);
u2 = cal(x,y);
addedge(u1,u2,v);
//	addedge(u2,u1,v);
//	printf("u1=%d u2=%d v=%d\n",u1,u2,v);
}
}
}

printf("Case #%d:\n%d\n",t,Kruskal(n*m));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: