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] ...
随机推荐
- vs code 本地调试配置
{ "name": "使用本机 Chrome 调试", "type": "chrome", "request& ...
- Linux进程管理(二)
目录 Linux进程管理(二) 参考 vmstat命令 top命令 Linux进程管理(二)
- redhat 7.6 网络配置
网卡配置目录 /etc/sysconfig/network-scripts/ 关闭网卡 $$ 打开网卡 ifdown ensp8 && ifup ensp8 重启网卡服务 servic ...
- Django 学习视图之FBV与CBV
一. CBV与FBV CBV:Class Based View FBV:Function Based View 我们之前写过的都是基于函数的view,就叫FBV.还可以把view写成基于类的,那就是C ...
- 科软-信息安全实验3-Rootkit劫持系统调用
目录 一 前言 二 Talk is cheap, show me the code 三 前期准备 四 效果演示 五 遇到的问题&解决 六 18.04的坑 七 参考资料 八 老师可能的提问 一 ...
- python 中的 *args 和 **kwargs
在阅读Python代码时,经常会看到如下函数的定义: def fun(*args, **kwargs): 很多同学可能会对此感到困惑,这个 * args和 **kwargs是什么东西.为啥会在源码中应 ...
- 简单易懂之python 中的map,filter,reduce用法
map(function,sequence) 把sequence中的值当参数逐个传给function,返回一个包含函数执行结果的list. 重点是结果返回一个列表,这样对返回的列表就可以干很多的活了. ...
- java并发之CopyOnWriteArraySet
java并发之CopyOnWriteArraySet CopyOnWriteArraySet是基于CopyOnWriteArrayList实现的,持有CopyOnWriteArrayList的内部对象 ...
- Linux centosVMware su命令、sudo命令、限制root远程登录
一.su命令 Linux系统中有些事情只有root用户才能做,普通用户不能做,这时候就需要临时切换到root身份了. [root@davery ~]# whoamiroot [root@davery ...
- 启动nginx出错:open() "/var/run/nginx/nginx.pid" failed (2: No such file or directory)
[emerg] open() "/var/run/nginx/nginx.pid" failed (2: No such file or directory) 解决:mkdir / ...