POJ1838
poj 1838
这道题主要是对并查集的考察,在这道题的解题过程中主要用到的算法就是并查集中的最基本的makeSet,findSet,unionSet
即前篇文章中所提到的:
makeSet(Elem x);主要实现的是,将传入的数据元素初始化为一个集合。
findSet(Elem x); 这个并查集中的原子算法主要实现的是查找到元素x所在的集合,
而这个集合主要使用集合中的祖先元素所唯一标识的。
unionSet(Elem x, Elem y);这个方法主要实现的是合并元素x,元素y所在的集合。
POJ 1838 解题报告
题目具体描述的什么意思就不翻译了,
输入样例中有N,K两个数值。
大致的意思是说,有N*N这么多个区域,区域上有相应的点(x,y)
当两个点point(x1,y1),(x2,y2) 之间是相邻的(neighbor)那么这两个点必须满足下面的条件之一:
1. x1==x2&&|y1-y2|==1
2. y2==y1&&|x1-x2|==1
根据相邻这一判定条件,可以把整个N*N个区域划分成m个区间(region)
即,region中的点是依靠两两之间作为neighbor来连接的。
现如今,需要你输出K个区间(region),并且要求这K个区间对应的区间中的点数之和达到最大。
(也就是说从m个区间中选取K个区间出来,是的这K个区间中的点数之和达到最大)
将m对应的数据结构排序(大到小),然后选取前K个,进行加和,然后进行输出,即可。
大致的算法流程如下:
readIn(N,K) for (i 0-> N-1)
{readIn(trees[i].x , trees[i].y) trees[i].key = i
} makeSet(trees[i].key); //finish initialization qsort(trees.x); for(i 0->N-2)
{
if(trees[i+1].x==trees[i].x && trees[i+1].y- trees[i].y==1)
unionSet(trees[i+1].key, trees[i].key);
} qsort(trees.y); for(i 0 ->N-2)
{
if(trees[i+1].y==trees[i].y && trees[i+1].x- trees[i].x==1)
unionSet(trees[i+1].key, trees[i].key);
} j=0; for(i 0-> N-1)
{
if(trees[i].key 是祖先节点)
setList[j++] = setNumber[trees[i].key];
} after this loop:
the value of j is the length of setList qsort(setList, j, sizeof(int ), compare_method); after this
get setList[0 .. k-1] value and add printf the sum
//union-find set #include<stdio.h>
#include<algorithm> typedef struct
{
int x;
int y;
int key;
}Tree;
//这个数据结构是根据问题而构建的
Tree trees[16001]; //这个数组用来存放节点的
int father[16001]; //father[i]用来表示的是trees[i]这个元素的父节点在trees中的位序下标
int rank[16001]; //这个是用来记录每个集合对应的树模型的树高,秩在并查集中通常以树高表示的,但也有以树状集合中的元素总数来代替的
int setNumber[16001]; //setNumber[i] 对应的是地i个元素的子元素的个数,如果i是它所在集合的祖先节点的话,setNumber[i]
int setList[16001]; //用于记录祖先节点所在的集合对应的集合中的总共的元素的个数的 int cmp(const void *a, const void *b)
{
return *(int *)b - *(int *)a;
}
//这个函数用于根据集合中元素的数目从大到小对setList数组进行排序
//对,因为是大到小排序,所以在返回值上面是参数2-参数1,
//如果是从小到大进行排序,则是参数1-参数2
int cmp_x(const void *a, const void *b)
{
Tree *t1, *t2; t1=(Tree*)a;
t2=(Tree*)b; if(t1->x!= t2->x)
return t1->x-t2->x;
else
return t1->y-t2->y;
}
//在对trees[i].x进行小到大排序的时候,如果trees[i].x的值相等,则排序的顺序将会根据trees[i].y的值从小到大进行相应的排序。
//又因为题中给出每个坐标上只有一棵香蕉树,所以测试数据不会有重复输入两次相同坐标的情况。 int cmp_y(const void *a, const void *b)
{
Tree *t1, *t2; t1 = (Tree*)a;
t2 = (Tree*)b; if(t1->y != t2->y)
return t1->y - t2->y;
else
return t1->x - t2->x;
} void makeSet(int x)
{
father[x] = x;
rank[x] = 0;
setNumber[x]=1;
} int findSet(int x)
{
if(father[x]!=x)
father[x] = findSet(father[x]); return father[x];
} void unionSet(int x, int y)
{
int rootx = findSet(x);
int rooty = findSet(y); if(rootx == rooty) return ;
if(rank[rootx] < rank[rooty])
{
father[rootx] = rooty;
setNumber[rooty] += setNumber[rootx];
} else
{
if(rank[rootx] == rank[rooty])
{
rank[rootx]++;
} father[rooty]=rootx;
setNumber[rootx]+= setNumber[rooty];
}
} int main()
{
int n, k, j, i, ans; scanf("%d %d", &n, &k); for(i = 0 ; i < n ; i++)
{
scanf("%d %d", &trees[i].x, &trees[i].y);
trees[i].key = i; makeSet(trees[i].key);
} qsort(trees, n, sizeof(Tree), cmp_x); for(i = 0 ; i < n-1; i++)
{
if(trees[i].x == trees[i+1].x && trees[i+1].y - trees[i].y ==1)
{
unionSet(trees[i].key, trees[i+1].key);
}
// printf("x:%d y:%d key:%d\n", trees[i].x, trees[i].y, trees[i].key);
} qsort(trees, n, sizeof(Tree),cmp_y); for(i = 0 ; i < n-1; i++)
{
if(trees[i].y == trees[i+1].y && trees[i+1].x-trees[i].x ==1)
{
unionSet(trees[i].key, trees[i+1].key);
} // printf("y:%d x: %d key:%d\n", trees[i].y, trees[i].x, trees[i].key);
} j = 0 ; for(i = 0 ; i < n ; i++)
{
if(father[trees[i].key]==trees[i].key)
{
setList[j++] = setNumber[trees[i].key];
} } qsort(setList, j, sizeof(int), cmp); //printf("region number:%d\n", j); ans = 0 ;
for(i = 0 ; i <k; i++)
{
ans+=setList[i];
//printf("setList[i] %d\n", setList[i]); } printf("%d\n", ans); return 0; }
memory/time/language/code length/date
| 604K | 172MS | C++ | 2197B | 2013-07-24 10:53:57 |
//考虑到这个rank也就是代表每个节点的秩,祖先元素的秩也就是树的高度,在本题中没有太多的实际用途,
//这是因为,在进行unionSet方法的时候,单纯地对元素个数进行比较,
//然后将少的元素所对应的集合的祖先节点所谓到元素多的集合的祖先节点的直系孩子
//也是可以实现相同的结果的,于是把rank变量从代码中进行删除
//然后稍稍更改一下unionSet(int x, int y )这个方法,代码如下:
void unionSet(int x, int y) { int rootx = findSet(x); int rooty = findSet(y);
if(rootx == rooty) return ;
if(setNumber[rootx]< setNumber[rooty])
{
father[rootx] = rooty;
setNumber[rooty] += setNumber[rootx];
}
else
{
father[rooty]=rootx;
setNumber[rootx]+= setNumber[rooty];
}
}
memory/time/language/code length/date
| 540K | 172MS | C++ | 2264B | 2013-07-24 11:28:48 |
POJ1838的更多相关文章
随机推荐
- ASP.NET 学习小记 -- “迷你”MVC实现(2)
Controller的激活 ASP.NET MVC的URL路由系统通过注册的路由表对HTTO请求进行解析从而得到一个用户封装路由数据的RouteData对象,而这个过程是通过自定义的UrlRoutin ...
- 【BZOJ】1002: [FJOI2007]轮状病毒 递推+高精度
1002: [FJOI2007]轮状病毒 Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同 ...
- 2014年辛星完全解读Javascript第二节
本小节我们讲解一下Javascript的语法,虽然js语言非常简单,它的语法也相对好学一些,但是不学总之还是不会的,因此,我们来一探究竟把. ********注释************* 1.我们通 ...
- C# zip/unzip with DotNet framework 4.5
add reference System.IO.Compression.FileSystem public class ZipHelper { public static string UnZip(s ...
- mysql的错误:The server quit without updating PID file /usr/local/mysql/data/door.pid).
mysql错误解决: 先 参考:http://www.jb51.net/article/48625.htm 参考第四条: mysql在启动时没有指定配置文件时会使用/etc/my.cnf配置文件,请打 ...
- jQuery UI dialog 的使用
今天用到了客户端的对话框,把 jQuery UI 中的对话框学习了一下. 准备 jQuery 环境 首先,我们创建一个按钮,点击这个按钮的时候,将会弹出一个对话框. 1 <input type= ...
- BZOJ 3955 Surely You Congest 解题报告
首先,我们可以求出源为 $1$ 号点的最短路图以及各个点到 $1$ 号点的最短路. 然后我们考虑那些距离不同的点,是一定不会发生拥堵现象的. 然后我们就只需要考虑那些距离相同的点,就相当于做一个最大流 ...
- 常用的python模块
http://tiankonghaikuo1000.blog.163.com/blog/static/18231597200812424255338/ adodb:我们领导推荐的数据库连接组件bsdd ...
- Design Tutorial: Learn from Life
Codeforces Round #270 B:http://codeforces.com/contest/472/problem/B 题意:n个人在1楼,想要做电梯上楼,只有1个电梯,每次只能运k个 ...
- mysql 监控工具monyog使用总结
1. 下载安装 2. 登录之后,查看 locked queries 2. 慢查询