【codevs2597/tyvj1602】团伙 解题报告
2015-09-19 19:37
323 查看
【codevs2597/tyvj1602】团伙 解题报告
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。
而且有一点是肯定的,就是A的朋友的朋友是A的朋友;A的敌人的敌人也是A的朋友。
两个强盗是同一伙的当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你至多有多少个强盗团伙。
输入的第一行为N(2<=N<=1000),表示强盗的个数(从1编号到N)。
第二行M(1<=M<=5000),表示信息条数。
以下M行,每行可能是F p q或是E p q,分别表示p和q是朋友,或是敌人。
假设输入不会产生矛盾
输出只有一行,表示最大可能的团伙数。
6
4
E 1 4
F 3 5
F 4 6
E 1 2
3
【解题思路】
经典的并查集题目,但是需要一点小小的技巧;
如果是朋友的话,直接把两个合并起来就行了;如果是敌人,那么就不合并;但是如果是敌人的敌人,就是朋友了,所以这种情况也要合并起来;
设一个数组,存下每一个点的所有的敌人,因为敌人的敌人是朋友,两个敌人的敌人都是这个点,所以他们俩一定是朋友,,所以我们要把这个点所有的敌人两两合并起来;
最后查找一下一共有几个集合,也就是有几个代表元素,就是最大的团伙的数目;
【代码】
在最后的时候,要注意再进行一次路径压缩,使所有集合里的点都指向一个代表元素。在合并的过程中路径压缩会有遗漏,会出现虽然在一个集合里,但指向不同的代表元素的情况。
描述
1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。 而且有一点是肯定的,就是A的朋友的朋友是A的朋友;A的敌人的敌人也是A的朋友。
两个强盗是同一伙的当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你至多有多少个强盗团伙。
输入格式
输入的第一行为N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示信息条数。
以下M行,每行可能是F p q或是E p q,分别表示p和q是朋友,或是敌人。
假设输入不会产生矛盾
输出格式
输出只有一行,表示最大可能的团伙数。
测试样例1
输入
6 4
E 1 4
F 3 5
F 4 6
E 1 2
输出
3【解题思路】
经典的并查集题目,但是需要一点小小的技巧;
如果是朋友的话,直接把两个合并起来就行了;如果是敌人,那么就不合并;但是如果是敌人的敌人,就是朋友了,所以这种情况也要合并起来;
设一个数组,存下每一个点的所有的敌人,因为敌人的敌人是朋友,两个敌人的敌人都是这个点,所以他们俩一定是朋友,,所以我们要把这个点所有的敌人两两合并起来;
最后查找一下一共有几个集合,也就是有几个代表元素,就是最大的团伙的数目;
【代码】
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,i,j,k,x,y,ans; int a[1005][1005],f[1005],num[10005]; bool b[1005]; char p; int find(int x) { if (f[x]==x) return f[x]; f[x]=find(f[x]); return f[x]; } void merge(int x,int y) { int n1=find(x); int n2=find(y); f[n2]=n1; return; } int main() { scanf("%d%d",&n,&m); for (i=1;i<=n;++i) f[i]=i; for (i=1;i<=m;++i) { cin>>p; scanf("%d%d",&x,&y); if (p=='F') merge(x,y); if (p=='E') { a[x][++num[x]]=y; a[y][++num[y]]=x; } } for (k=1;k<=n;++k) { for (i=1;i<=num[k];++i) for (j=i;j<=num[k];++j) merge(a[k][i],a[k][j]); } for (i=1;i<=n;++i) k=find(i); for (i=1;i<=n;++i) b[f[i]]=true; for (i=1;i<=n;++i) if (b[i]) ans++; printf("%d",ans); return 0; }【犯的错误】
在最后的时候,要注意再进行一次路径压缩,使所有集合里的点都指向一个代表元素。在合并的过程中路径压缩会有遗漏,会出现虽然在一个集合里,但指向不同的代表元素的情况。
相关文章推荐
- 自定义控件>智能文本框(InputView)
- 工厂模式与抽象工厂模式小览(二)
- 约瑟夫环的问题
- 链接字符串放在配置文件中
- Java基础知识强化38:StringBuffer类之StringBuffer的添加功能
- POJ-1887
- C++ 空类默认产生的类成员函数
- 老猴子排序
- 树的子结构
- Java基金会——JUnit
- Linux内核笔记——内存管理之slab分配器
- 多态解读
- netstat查看端口指令
- GoldenGate 配置
- 本库主要提供一些类和一些函数来比较不同序列对象
- JAVA学习资源种子
- Unity3d NGUI伪自适应
- 阶梯问题
- 测试要点的提取
- QT对话框中show和exec的区别