[LUOGU] 1892 团伙
题目描述
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:
我朋友的朋友是我的朋友;
我敌人的敌人也是我的朋友。
两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。
输入输出格式
输入格式:
输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示关于强盗的信息条数。 以下M行,每行可能是F p q或是E p q(1<=p q<=N),F表示p和q是朋友,E表示p和q是敌人。输入数据保证不会产生信息的矛盾。
输出格式:
输出文件gangs.out只有一行,表示最大可能的团伙数。
输入输出样例
输入样例#1: 复制
6
4
E 1 4
F 3 5
F 4 6
E 1 2
输出样例#1: 复制
3
最难处理的是敌人这块问题,最开始想到用一个敌人邻接表存下所有的直接联系的敌人,然后每次加入敌人的时候将待加入的点和通过该点到达的所有点作为朋友并起来,一开始只有90分,忽略了无向图(这数据不行啊。。),代码并不算太慢。
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#define MAXN 20000
using namespace std;
//priority_queue
int m,n;
int fa[MAXN];
int ans[MAXN];
struct Edge{
int next,to;
}enode,e[MAXN];
int ct=0;
int head[MAXN];
//vector<Edge> e;
//inline void add(int x,int y){
// head[x]=e.size() ;
// enode.to = y;
// enode.next = head[x];
// e.push_back(enode);
//
//}
void add(int x,int y){
e[++ct].next= head[x];
e[ct].to = y;
head[x]=ct;
}
int fnd(int x){
// cout<<x<<endl;
if(fa[x]==x) return x;
return fa[x]=fnd(fa[x]);
}
void cat(int x, int y){
// x=fnd(x);
// y=fnd(y);
fa[y]=x;
}
int main(){
// freopen("testdata.in","r",stdin);
memset(head,-1,sizeof(head));
cin>>n>>m;
char sta;
int x,y;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
// scanf("%c %d %d",&sta,&x,&y);
cin>>sta>>x>>y;
// cout<<"XXX: "<<x<<" "<<y<<endl;
if(sta=='E'){
for(int j=head[x];j!=-1;j=e[j].next){
// cout<<"J:"<<j<<endl;
int u=fnd(e[j].to),v=fnd(y);
if(u!=v) cat(u,v);
}
for(int j=head[y];j!=-1;j=e[j].next){//LSM庇佑
int u=fnd(e[j].to),v=fnd(x);
if(u!=v) cat(u,v);
}
add(x,y);
//
add(y,x);
}else{
int u=fnd(x),v=fnd(y);
if(u!=v) cat(u,v);
}
}
for(int i=1;i<=n;i++){
ans[i]=fnd(i);
}
sort(ans+1,ans+1+n);
int cnt=1;
for(int i=1;i<n;i++) if(ans[i]!=ans[i+1]) cnt++;
cout<<cnt;
return 0;
}
嗯。。最后那块处理计数的部分实在是丑陋。
然后静静教了一种神奇的方法,并查集的补集。
通过把敌人(i+N)作为朋友来加入,大大简化了代码,所有人都是朋友!
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#define MAXN 5005
using namespace std;
//priority_queue
int m,n;
int fa[MAXN];
int fnd(int x){
if(x==fa[x]) return x;
return fa[x]=fnd(fa[x]);
}
void cat(int x,int y){
x=fnd(x);
y=fnd(y);
fa[y]=x;
}
bool vis[MAXN];
int main(){
cin>>n>>m;
for(int i=1;i<=n*2+3;i++) fa[i]=i;
char sta;
int x,y;
for(int i=1;i<=m;i++){
cin>>sta>>x>>y;
if(sta=='E'){
fa[fnd(y)]=fnd(x+n);
fa[fnd(y+n)]=fnd(x);
}else{
fa[fnd(x)]=fnd(y);
}
}
for(int i=1;i<=n;i++){
vis[fnd(i)]=true;
}
int cnt=0;
for(int i=1;i<=n*2;i++){
if(vis[i]) cnt++;
}
cout<<cnt;
return 0;
}
PS:最后处理联通块计数也很好。。
[LUOGU] 1892 团伙的更多相关文章
- Luogu P1892 团伙
Luogu P1892 团伙 这是道很简单的并查集-- 不,它并不简单. 这道题考了一个叫做反集的东西. 也就是说: 如果$a$和$b$是敌人,合并$n+b$和$a$,$n+a$和$b$: 如果$c$ ...
- BZOJ 1370: [Baltic2003]Gang团伙(luogu 1892)(种类并查集)
题面: bzoj题面有误,还是看luogu的吧 https://www.luogu.org/problemnew/show/P1892 题解: 种类并查集.. 因为有敌人的敌人是朋友这个条件,所以需要 ...
- 【Luogu P2024&P1892】食物链&团伙(并查集拓展域)
Luogu P1892 Luogu P2024 这两道一眼看过去很容易发现可以用并查集来做--但是当我们仔细阅读题面后,会发现其实并没有那么简单. 我们知道并查集可以很轻松地维护具有传递性的信息,也就 ...
- Luogu P1892 P1525 团伙 关押罪犯
(怎么都是抓罪犯 怪不得写法差不多) 团伙 关押罪犯 并查集.以"敌人的敌人是朋友"的思路来处理.所以增加一个e/E数组来存储敌人. 关押罪犯还用到了贪心的思路.将冲突值从大到小排 ...
- Luogu P1195/P1892 口袋的天空/BOI团伙 【最小生成树/并查集】By cellur925
其实这俩题挺水的,团伙拿下了一血,但是感觉还是写一下博客比较好x. 一.团伙 题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是 ...
- Luogu P1892 [BOI2003]团伙
P1892 [BOI2003]团伙 题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人 ...
- code vs 2597 团伙
题目描述 Description 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友 ...
- 洛谷 P1892 [BOI2003]团伙(并查集)
嗯... 题目链接:https://www.luogu.org/problemnew/show/P1892 通过读题可以很清楚的发现这是一个并查集的题,并且要有两个集合: 若他们p和q是朋友,则存入第 ...
- codevs 2597 团伙
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么 ...
随机推荐
- 在虚拟机中设置NAT模式实现主机和虚拟机的通信
1.打开虚拟机,对几个节点进行网络连接的设置.虚拟机设置/网络连接,选择“NAT模式” 2.编辑—>虚拟网络编辑器来查看NAT模式中所用到的网段. 从上图可以看出,NAT中的子网IP是192.1 ...
- TensorFlow数据集(二)——数据集的高层操作
参考书 <TensorFlow:实战Google深度学习框架>(第2版) 一个使用数据集进行训练和测试的完整例子. #!/usr/bin/env python # -*- coding: ...
- [NOIP2014]无线网站发射器选址
Description 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网.假设该城市的布局为由严格平行的129条东西向街道和129条南北向街道所形成的网格状, ...
- 50 个加速包都抢不到车票,还不如这个 Python 抢票神器!
又到了一年一度的抢票大战,本来就辛苦劳累了一年,想着可以早点订到票跟家里人团聚.所以有挺多的人,宁愿多花些钱去找黄牛买票.但今年各种抢票软件的横行,还有官方出的加速包,导致连黄牛都不敢保证能买到票.你 ...
- django (三) admin后台系统
admin后台系统 1. 安装MySQL 1,安装mysql: sudo apt install mysql-server (安装过程中输入密码并牢记) 2,安装后进入mysql: mysql ...
- Spark无法创建新线程
Spark提交程序报错,无法创建新的线程 原因是因为这台公用机器上跑的进程太多了,需要修改Linux参数,允许用户最大进程数 查看允许用户最大进程数配置 ulimit -a 修改允许用户最大进程数配置 ...
- 系统讲解一下,Dao,Entity,Servlet,Action各自有什么东西-Java/Web开发
dao 主要是一些接口,里面定义了一些用于增删改查的方法名 daoImpl 就是对dao的具体实现 Service 同上,也是一些接口,主要是用来调用dao层的一些方法,所以这里定义的方法一般都定义好 ...
- 引用library之——带有自定义属性的自定义控件的library包
一般来讲,当自定义一个控件Panel并且此控件有自定义属性时(例如:panel:closedHandle="@drawable/foot_bar_right"),xml中需要定义此 ...
- SPM-软件项目管理之感想
这学期开始选择选修课的时候是需要把每节课都过一遍的.当我上完SPM那节课的时候,我就已经决定要选这门课了,尽管还有其他的课我都还没上过.由于这节课是双语教学-中文老师兼外籍老师,这样的方式感觉很新颖, ...
- JS 语言基础
两个变量 相加 var s="今天下雨了"; var i=10; alert(i+s); 这里的i+s是拼接的意思 显示出来是 今天下雨了10 假设我改 s="2 ...