[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年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么 ...
随机推荐
- hyperledger fabric 1.0.5 分布式部署 (七)
fabric 使用 fabric-ca 服务 准备部分 首先需要用户从github上download fabric-ca 的工程代码 cd $GOPATH/src/github.com/hyperle ...
- 笔记-JavaWeb学习之旅11
请求转发:一种在服务器内部的资源跳转方式 使用步骤 1.通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path) ...
- 全球首款iOS模拟器出炉!在违法的边缘疯狂试探
对于许多智能手机用户,特别是手游玩家来说,在手机屏幕的方寸之间进行操作显然并非特别方便,而且在多年之前,由于手机配置不足,也导致了用PC来玩手游的需求不断涌现.彼时,BlueStacks及夜神等一众A ...
- C【C#公共帮助类】分页逻辑处理类
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Comm ...
- Java | 基础归纳 | 随机数应用
Java中一般有两种随机数,一个是Math中random()方法,一个是Random类. Math.random();//返回0~1的中随机数值 Random random = new Random( ...
- windows安装redis和PHP redis扩展
1.安装Redis (1)这里选择在github官网上下载Redis,地址:Redis下载地址 下载压缩包(如下图),并解压到本地目录,我放在D:\wamp\redis\redis-windows ( ...
- Storm编程入门API系列之Storm的Topology默认Workers、默认executors和默认tasks数目
关于,storm的启动我这里不多说了. 见博客 storm的3节点集群详细启动步骤(非HA和HA)(图文详解) 建立stormDemo项目 Group Id : zhouls.bigdata Art ...
- 如何查找Oracle某列值相同的字段
相关的sql语句如下 select xm_guidfrom T_NZYDKgroup by xm_guidhaving count (*)>1
- arcengine,c# 二次开发
plication.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ESRI.ArcGIS.Ru ...
- 我喜欢的两个js类实现方式 现在再加上一个 极简主义法
闭包实现 变量是不会变的:) var myApplication = function(){ var name = 'Yuri'; var age = '34'; var status = 'sing ...