POJ1703 && POJ2942 &&POJ 1182 并查集 这个做法挺巧妙
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 37242 | Accepted: 11483 |
Description
two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.)
Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:
1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.
2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.
Input
Output
Sample Input
1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4
Sample Output
Not sure yet.
In different gangs.
In the same gang.
题意是在Tadu这个城市有两个团伙。
给出D i j的意思是说i和j不是一个团伙的。
给出A i j的意思是根据已知的信息,能不能确定i和j是一个团伙的,如果确定是一个团伙的,输出“In different gangs.”。如果确定不是一个团伙的,输出“In the same gang.”。如果不能确定,输出“Not sure yet.”
之前使用并查集都是判断两个人是不是在一个集合里,这次要确定地判断两个人不在集合里,所以想法就是添加无用的N个元素作为桥梁。i k不在一个集合中,k j不在一个集合中,说明i j在一个集合中,那我把i k j都放入集合中,只不过k是我查询永远都不会用到的元素,所以就是添加元素时 i k+N,k+N j添加到集合中。所以当我查询k+N,j 发现他们在一个集合中时,就恰恰说明了k和j在两个团伙里面。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; char oper[5];
int n,m,num;
int pre[200015]; int findpre(int x)
{
while(x!=pre[x])
{
x=pre[x];
}
return x;
} void union_set(int x,int y)
{
int pre_x=findpre(x);
int pre_y=findpre(y); if(pre_x == pre_y)
return;
else if(pre_x>pre_y)
{
int temp = pre_x;
pre_x = pre_y;
pre_y = temp;
}
pre[pre_y]=pre_x;
} bool same(int x,int y)
{
return findpre(x) == findpre(y);
} int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout); int test,i,temp1,temp2;
scanf("%d",&test); while(test--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=2*n;i++)
{
pre[i]=i;
}
for(i=1;i<=m;i++)
{
scanf("%s%d%d",oper,&temp1,&temp2);
if(oper[0]=='A')
{
if(same(temp1,temp2))
{
printf("In the same gang.\n");
}
else if(same(temp1+n,temp2)||same(temp1,temp2+n))
{
printf("In different gangs.\n");
}
else
{
printf("Not sure yet.\n");
} }
else if(oper[0]=='D')
{
union_set(temp1,temp2+n);
union_set(temp1+n,temp2);
}
}
}
//system("pause");
return 0;
}
POJ2942与此类似,代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; int n,m;
int pre[200015]; int findpre(int x)
{
while(x!=pre[x])
{
x=pre[x];
}
return x;
} void union_set(int x,int y)
{
int pre_x=findpre(x);
int pre_y=findpre(y); if(pre_x == pre_y)
return;
else if(pre_x>pre_y)
{
int temp = pre_x;
pre_x = pre_y;
pre_y = temp;
}
pre[pre_y]=pre_x;
} bool same(int x,int y)
{
return findpre(x) == findpre(y);
} int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout); int test,i,j,temp1,temp2;
scanf("%d",&test); for(i=1;i<=test;i++)
{
printf("Scenario #%d:\n",i);
scanf("%d%d",&n,&m); for(j=1;j<=2*n;j++)
{
pre[j]=j;
} bool flag=false;
for(j=1;j<=m;j++)
{
scanf("%d%d",&temp1,&temp2); if(flag)continue; if(same(temp1,temp2))
{
flag=true;
continue;
}
union_set(temp1,temp2+n);
union_set(temp1+n,temp2);
}
if(flag)
{
printf("Suspicious bugs found!\n\n");
}
else
{
printf("No suspicious bugs found!\n\n");
}
} //system("pause");
return 0;
}
POJ1182是把集合弄成了3个,那与此同理,就是x,x+n,x+2*n的区别,用x,y+n表示A吃B的集合。再对每一个语句进行排除,得到答案。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; int n,m,num;
int pre[150015]; int findpre(int x)
{
while(x!=pre[x])
{
x=pre[x];
}
return x;
} void union_set(int x,int y)
{
int pre_x=findpre(x);
int pre_y=findpre(y); if(pre_x == pre_y)
return;
else if(pre_x>pre_y)
{
int temp = pre_x;
pre_x = pre_y;
pre_y = temp;
}
pre[pre_y]=pre_x;
} bool same(int x,int y)
{
return findpre(x) == findpre(y);
} int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout); int oper,i,x,y,ans;
scanf("%d%d",&n,&m); ans=0;
for(i=1;i<=3*n;i++)
{
pre[i]=i;
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&oper,&x,&y);
if(x<=0||x>n||y<=0||y>n)
{
ans++;
continue;
}
if(oper==1)
{
if(same(x,y+n)||same(x,y+2*n)||same(x+n,y))
{
ans++;
continue;
}
union_set(x,y);
union_set(x+n,y+n);
union_set(x+2*n,y+2*n);
}
else if(oper==2)
{
if(x==y||same(x,y)||same(x+n,y)||same(x,y+2*n))
{
ans++;
continue;
}
union_set(x,y+n);
union_set(x+n,y+2*n);
union_set(x+2*n,y);
}
}
printf("%d\n",ans);
//system("pause");
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
POJ1703 && POJ2942 &&POJ 1182 并查集 这个做法挺巧妙的更多相关文章
- POJ 1182 并查集
Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到 ...
- 食物链 POJ - 1182 (并查集的两种写法)
这是一个非常经典的带权并查集,有两种写法. 1 边权并查集 规定一下,当x和y这条边的权值为0时,表示x和y是同类,当为1时,表示x吃y,当为2时,表示x被y吃. 一共有三种状态,如图,当A吃B,B吃 ...
- poj 1182 并查集高级应用
C - 是谁站在食物链的顶端 Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:10000KB ...
- poj 1984 并查集
题目意思是一个图中,只有上下左右四个方向的边.给出这样的一些边, 求任意指定的2个节点之间的距离. 就是看不懂,怎么破 /* POJ 1984 并查集 */ #include <stdio.h& ...
- poj 1797(并查集)
http://poj.org/problem?id=1797 题意:就是从第一个城市运货到第n个城市,最多可以一次运多少货. 输入的意思分别为从哪个城市到哪个城市,以及这条路最多可以运多少货物. 思路 ...
- POJ 2492 并查集扩展(判断同性恋问题)
G - A Bug's Life Time Limit:10000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u S ...
- POJ 2492 并查集应用的扩展
A Bug's Life Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 28651 Accepted: 9331 Descri ...
- POJ 3228 [并查集]
题目链接:[http://poj.org/problem?id=3228] 题意:给出n个村庄,每个村庄有金矿和仓库,然后给出m条边连接着这个村子.问题是把所有的金矿都移动到仓库里所要经过的路径的最大 ...
- poj 1733 并查集+hashmap
题意:题目:有一个长度 已知的01串,给出多个条件,[l,r]这个区间中1的个数是奇数还是偶数,问前几个是正确的,没有矛盾 链接:点我 解题思路:hash离散化+并查集 首先我们不考虑离散化:s[x] ...
随机推荐
- Linux centos7 Linux网络相关、firewalld和netfilter、netfilter5表5链介绍、iptables语法
一. Linux网络相关 yum install net-tools ifconfig查看网卡ip ifup ens33开启网卡 ifdown ens33关闭网卡 设定虚拟网卡ens33:0 mii- ...
- MongoDB基础篇1:安装和服务配置
一.下载 请前往官网下载community版本MongoDB,我当前可见最新版本是3.6.4 https://www.mongodb.com/download-center#community 如需下 ...
- CSS - 插入图片img和背景图片
1. img插入图片,用的最多,比如产品展示类 .section img { width: 200px;/* 插入图片更改大小 width 和 height */ height: 210px; mar ...
- js中每隔一段时间执行一次
window.setInterval("flushs()",1000);
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表格:表示一个危险的操作
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Linux CentOS7 VMware usermod命令、用户密码管理、mkpasswd命令
一. usermod命令 usermod可用来修改用户帐号的各项设定 -c, --comment 注释 GECOS 字段的新值 -d, --home HOME_DIR 用户的新主目录 -e, --ex ...
- 输入、输出(iostream)
在一个程序当中输入和输出都扮演着重要的角色,所以掌握基本输入输出是入门一门语言所必不可少的.本文主要简单叙述java的输入和输出. package ios; import java.util.Scan ...
- Day3-A-Problem H. Monster Hunter HDU6326
Little Q is fighting against scary monsters in the game ``Monster Hunter''. The battlefield consists ...
- JavaScript(3)---事件冒泡、事件捕获
JavaScript(3)---事件冒泡与事件捕获 一.理解冒泡与捕获 假设有这么一段代码 <body> <div><p>标签</p> </div ...
- 「NOIP2014」飞扬的小鸟
传送门 Luogu 解题思路 考虑 \(\text{DP}\) 设 \(dp[i][j]\) 表示飞到 \((i, j)\) 这个点的最小触屏次数. 转移其实比较显然,但问题是每次上升时都可以点很多次 ...