2015百度之星 初赛2 连接的管道 最小生成树
2015-05-31 22:00
274 查看
题意:老 Jack 有一片农田,以往几年都是靠天吃饭的。但是今年老天格外的不开眼,大旱。所以老 Jack 决定用管道将他的所有相邻的农田全部都串联起来,这样他就可以从远处引水过来进行灌溉了。当老
Jack 买完所有铺设在每块农田内部的管道的时候,老 Jack 遇到了新的难题,因为每一块农田的地势高度都不同,所以要想将两块农田的管道链接,老 Jack 就需要额外再购进跟这两块农田高度差相等长度的管道。
现在给出老 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; }
相关文章推荐
- asp.net 未能写入输出文件--“拒绝访问”的解决办法
- wep api authenticate
- JavaScript中的setInterval用法
- 第二阶段每日站立会议Fifth Day
- 转载:python爬虫实践之模拟登录
- lambda的常见用法:传递一个函数的结果作为另一个函数的参数
- 苹果开发 笔记(33)常用组件笔记
- Numpy学习笔记1-基本类型
- 图书管理系统测试计划
- php数字分页
- 机器学习 Machine Learning
- C语言小程序
- 多个活动分区
- 兼容
- 通过传入的两个点计算他们之间的角度
- [Java]Swing树状组件JTree
- OpenCV2学习笔记(二十一):GPU模块小记
- [hiho 22]线段树-lazy标记的下放
- python unicode
- Java快速排序 分别以数组0位作为基准 和最后一位作为基准的排序演示