poj1703(各种姿势)
题目链接:http://poj.org/problem?id=1703
题意:有n个人分别属于两个团伙,接下来m组形如 ch, x, y的数据,ch为“D"表示 x, y属于不同的团伙,ch为"A"表示询问x,y书否属于同一个团伙;
解法1:我们可以用jion(x, y)属于同一个团伙,jion(x+n, y)表示x属于第二个团伙,y属于第一个团伙,jion(x, y+n)表示x属于第一个团伙,y属于第二个团伙;
那么对于每组不同团伙的x, y我们只需要jion(x+n, y) ,jion(x, y+n)即可;查询时判断x,y或者x+n, y+n根节点是否相同即可,因为集合关系jion表示属于同一团伙,根节点相同则属于相同团伙,若x, y+n,或者x+n, y根节点相同则属于不同团伙,其余情况即为不能确定;
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN (100000+10) //***MAXN后面做下标时MAXN*2,要加括号,不然会越界!!run time error!!!
using namespace std; int pre[MAXN*], rank[MAXN*]; //***rank用来区分树的高度,但其不存储树的具体高度 int find(int x){
int r = x;
while(pre[r]!=r){
r = pre[r];
}
int i = x; //****路径压缩
while(pre[i]!=r){
int gg = pre[i];
pre[i] = r;
i = gg;
}
return r;
} void jion(int x, int y){
int xx = find(x);
int yy = find(y);
if(rank[xx]>rank[yy]){ //***启发式合并,就是把矮的树合并到高的树地下,把合并时间从0(n)降到o(logn)
pre[yy] = xx;
}else{
pre[xx] = yy;
if(rank[xx] == rank[yy]){ //**若树的标记高度一样,那么给合并后作为父亲的树rank+1,以区分树的高度
rank[xx]++;
}
}
} int main(void){
int t;
scanf("%d", &t);
while(t--){
int n, m;
scanf("%d%d", &n, &m);
for(int i=; i<=*n; i++){
pre[i] = i;
rank[i] = ;
}
while(m--){
char ch[];
int x, y;
scanf("%s%d%d", ch, &x, &y);
if(ch[]=='D'){
jion(x, y+n);
jion(x+n, y);
}else{
if(find(y+n)==find(x)||find(x+n)==find(y)){
printf("In different gangs.\n");
}else if(find(x)==find(y)||find(x+n)==find(y+n)){
printf("In the same gang.\n");
}else{
printf("Not sure yet.\n");
}
}
}
}
return ;
}
方法2:用vis数组标记不同的集合,如:vis[x]=y,表示与x不同集合的点y;
用并查集合并属于同一类的点集;
代码:
#include <iostream>
#include <stdio.h>
#define MAXN 100010
using namespace std; int pre[MAXN], vis[MAXN], rank[MAXN]; //***vis标记不同集合的编号,rank区分树高
//***vis[x]=y,表示记录x与y不同集合,相当于无向图,所以需双向标记 /*int find(int x){ //**400+ms
int r = x;
while(pre[r]!=r){
r = pre[r];
}
int i = x;
while(i!=r){
int gg = pre[i];
pre[i] = r;
i = gg;
}
return r;
}*/ int find(int x){ //**306ms (再加启发式合并=282ms)
return pre[x]==x ? x : pre[x] = find(pre[x]);
} void jion(int x, int y){
int xx = find(x);
int yy = find(y);
if(rank[xx] > rank[yy]){
pre[yy] = xx;
}else{
pre[xx] = yy;
if(rank[xx] == rank[yy]){
rank[yy]++;
}
}
} int main(void){
int t;
scanf("%d", &t);
while(t--){
int n, m;
scanf("%d%d", &n, &m);
for(int i=; i<=n; i++){
pre[i] = i;
vis[i] = ;
rank[i] = ;
}
while(m--){
char ch[];
int x, y;
scanf("%s%d%d", ch, &x, &y);
if(ch[]=='D'){
if(vis[x]== && vis[y]==){ //**x, y都没出现过
vis[x] = y;
vis[y] = x;
}else if(vis[x]==){ //**x没出现过
vis[x] = y;
jion(x, vis[y]);
}else if(vis[y]==){ //**y没出现过
vis[y] = x;
jion(y, vis[x]);
}else{ //**都出现过
jion(x, vis[y]);
jion(y, vis[x]);
}
}else{
if(find(x)==find(y)){
printf("In the same gang.\n");
}else if(find(x)==find(vis[y])){
printf("In different gangs.\n");
}else{
printf("Not sure yet.\n");
}
}
}
}
return ;
}
方法3:
种类并查集,先区分能不能辨别的情况,然后只要考虑同和不同两种情况,可以用rank数组记录当前节点x与其根节点是否相同的信息,1表相同,0表不同;
代码:
#include <iostream>
#include <stdio.h>
#define MAXN 100010
using namespace std; int pre[MAXN], rank[MAXN]; //**rank储存x与x的根节点是否相同的信息,1表相同,0表不同 int find(int x){
if(x==pre[x]){
return pre[x];
}
int xx = pre[x];
pre[x] = find(pre[x]);
rank[x] = (rank[x] + rank[xx])&; //**压缩路径,x的根节点改变了,rank[x]也要改变
return pre[x];
} void jion(int x, int y){
int xx = find(x);
int yy = find(y);
if(xx!=yy){
pre[yy] = xx;
rank[yy] = (rank[x] + rank[y] + )&; //**合并只需改变yy之前的rank值
}
} int main(void){
int t;
scanf("%d", &t);
while(t--){
int n, m;
scanf("%d%d", &n, &m);
for(int i=; i<=n; i++){
pre[i] = i;
rank[i] = ;
}
while(m--){
char ch[];
int x, y;
scanf("%s%d%d", ch, &x, &y);
if(ch[]=='D'){
jion(x, y);
}else{
if(find(x)==find(y)){
if(rank[x]==rank[y]){
printf("In the same gang.\n");
}else{
printf("In different gangs.\n");
}
}else{
printf("Not sure yet.\n");
}
}
}
}
return ;
}
poj1703(各种姿势)的更多相关文章
- 内网劫持渗透新姿势:MITMf简要指南
声明:本文具有一定攻击性,仅作为技术交流和安全教学之用,不要用在除了搭建环境之外的环境. 0×01 题记 又是一年十月一,想到小伙伴们都纷纷出门旅游,皆有美酒佳人相伴,想到这里,不禁潸然泪下.子曰:& ...
- 判断是否为gif/png图片的正确姿势
判断是否为gif/png图片的正确姿势 1.在能取到图片后缀的前提下 1 2 3 4 5 6 7 8 9 //假设这是一个网络获取的URL NSString *path = @"http:/ ...
- 在Linux(ubuntu server)上面安装NodeJS的正确姿势
上一篇文章,我介绍了 在Windows中安装NodeJS的正确姿势,这一篇,我们继续来看一下在Linux上面安装和配置NodeJS. 为了保持一致,这里也列举三个方法 第一个方法:通过官网下载安装 h ...
- 聊聊 Web 项目二维码生成的最佳姿势
在设计和实现的过程之后,你永远不知道部署上去的程序会已什么样的姿势运行. 本篇借一次生成二维码逻辑的不同实现,阐述 Web 项目中二维码生成的正确姿势. 文中如有批量,欢迎各位看客老爷拍砖.试运行前5 ...
- Lua手动编译姿势
LUA-5.3.3.tar.gz Lua源码+链接2016年5月30日更新 手动编译姿势: 已经装有VS2010 使用VS自带的 cl.exe以及 VS命令簿 打开文件地址 运行自己的bat文件 my ...
- 浅谈OC对象初始化的三种姿势
一.普通程序猿普通程序员使用最常见路人姿势等场.普普通通,纯属陆仁辈. 陆仁贾写法: // view 1 UIView *v1 = [UIView alloc] initWithFrame:CGRec ...
- 与MySQL传统复制相比,GTID有哪些独特的复制姿势?
与MySQL传统复制相比,GTID有哪些独特的复制姿势? http://mp.weixin.qq.com/s/IF1Pld-wGW0q2NiBjMXwfg 陈华军,苏宁云商IT总部资深技术经理,从事数 ...
- 快速了解IOC的几种姿势
一.首先我们了解IOC如何注入的几种姿势 构造函数注入(Constructor Injection) Ioc容器会智能的选择和调用合适的构造函数以创建依赖的对象.如果被选择的构造函数具有相应的参数,I ...
- xpath轴的正确使用姿势
网上看了许多关于轴的介绍,只介绍了语法,而没有明说具体实际中该怎么使用,百思不得其解. 背景--python中使用xpath: ----------------------------------- ...
随机推荐
- vim 编辑器的设置
vi编辑器的配置:http://blog.mcuol.com/User/fenghua/Article/17411_1.htm ******************************vim ~/ ...
- DOM之节点层次
1.1 Node类型 DOM1级定义了一个Node接口,该接口将由DOM中的所有节点类型实现.这个Node接口在JS中是作为Node类型实现的:除了IE之外,其他浏览器可访问这个类型.JS中的所有节点 ...
- 如何学习caffe
知乎上的讨论:https://www.zhihu.com/question/27982282 从0开始山寨caffe系列:http://www.cnblogs.com/neopenx/archive/ ...
- Linux环境变量的添加设置
以前一直都记着的,后来做的事情多了就什么都忘的差不多了. 在Linux中,环境变量一般添加有这么几个地方: 1./etc/profile 这个目录设置的变量为整个系统的全局变量,所有的用户通用,一般不 ...
- 37 网络相关函数(五)——live555源码阅读(四)网络
37 网络相关函数(五)——live555源码阅读(四)网络 37 网络相关函数(五)——live555源码阅读(四)网络 简介 10)MAKE_SOCKADDR_IN构建sockaddr_in结构体 ...
- 4-python学习——数据操作
4-python学习--数据操作 参考python类型转换.数值操作(收藏) Python基本运算符 数据类型转换: 有时候,可能需要执行的内置类型之间的转换.类型之间的转换,只需使用类名作为函数. ...
- ndk学习5: ndk中使用c++
默认情况下ndk不支持标准C++库,异常, rtti等 在ndk文档有关于C++ support的详细介绍 一. 使用C++标准库 介绍: 默认是使用最小额度的C++运行时库, 在Applic ...
- linux系统vsftpd登陆慢卡怎么办
linux系统vsftpd登陆慢卡怎么办 浏览:145 | 更新:2013-12-31 00:50 vsftpd是linux系统中的一款ftp软件,用它可以实现文件,数据上传与下载,但有些用户会发现v ...
- 基于“事件”驱动的领域驱动设计(DDD)框架分析
摘抄自 从去年10月份开始,学了几个月的领域驱动设计(Domain Driven Design,简称DDD).主要是学习领域驱动设计之父Eric Evans的名著:<Domain-driven ...
- Linux安装字体
用惯了Win7的字体,感觉雅黑看着很舒服,就动手在Linux安装下,简单描述下: 第一步:百度一下,找到微软雅黑字体(.ttf)下载 第二步:把下载的字体放到cd /usr/share/fonts/z ...