[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年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么 ...
随机推荐
- PostgreSQL - update语句怎么关联多个表
问题 对于select语句,我们可以通过join/outer join来关联多个表:但是对于update语句,是不能直接通过join/outer join来关联多表数据的,这里仅针对PostgreSQ ...
- Ubuntu设置右键打开终端
1:设置Ubuntu右键打开终端. Ctrl+Alt+T 打开终端 $ sudo apt-get ins tall nautilus-open-terminal 重启系统 2:进入root用户认证失败 ...
- 利用Common-BeanUtils封装请求参数
一.BeanUtils介绍 commons-beanutils是利用反射机制对JavaBean的属性进行处理,提供了对于JavaBean的各种处理方法.众所周知,一个JavaBean通常包含了大量的属 ...
- 092 Reverse Linked List II 反转链表 II
反转从位置 m 到 n 的链表.用一次遍历在原地完成反转.例如:给定 1->2->3->4->5->NULL, m = 2 和 n = 4,返回 1->4-> ...
- [已读]ppk谈javascript
读的第一本javascript方面的书籍,印象也比较深.ppk对浏览器兼容很有研究~~可以看看他的www.quirksmode.org
- 04.Javascript——入门一些方法记录之iterable
遍历Array可以采用下标循环,遍历Map和Set就无法使用下标.为了统一集合类型,ES6标准引入了新的iterable类型,Array.Map和Set都属于iterable类型. 具有iterabl ...
- ruby字符串处理
1. str="abc123"puts str[0].chr => a puts str[0] =>a的ascii码 2.中文字符串的正则 ...
- git与GitHub(二)
昨天在安装完git之后,出了一个问题,虽然暂时有解决的办法,但是由于电脑中了病毒并且配置低下等原因,这个问题的解决办法目前还有待考证.遇到的问题是这样的: 前提是想试一下git在命令行里的命令:于是: ...
- STL使用迭代器逆向删除
网上有很多这种例子: void erase(vector<int> &v) { for(vector<int>::reverse_iterator ri=v.rbegi ...
- while嵌套应用二:九九乘法表
__author__ = 'zht' #!/usr/bin/env python # -*- coding: utf-8 -*- ''' #努力学习每一天 ''' #while嵌套应用二:九九乘法表 ...