|
随笔分类 -
并查集
摘要:题意:成员A与成员B通话 ,成员B与成员C通话,则 ABC即为一个团伙,一共有若干个团伙,每个团伙的人数大于2且相互通话时间超过一定值即为黑帮,每个黑帮伙里有一个BOSS,boss是与各个成员打电话最多的那一个,找出所有黑帮boss跟与之相应成员数,按字典序排列。分析:通话姓名是字符串,不好直接构图,离散化一下,在用并查集确定团伙,在查找黑帮与BOSS#include#include#include#include#include#includeusing namespace std;int bossLen[2099];int oneLen[2099];int Link[2099];int n
阅读全文
摘要:http://pat.zju.edu.cn/contests/pat-a-practise/1021无环连通图也可以视为一棵树,选定图中任意一点作为根,如果这时候整个树的深度最大,则称其为 deepest root。 给定一个图,按升序输出所有 deepest root。如果给定的图有多个连通分量,则输出连通分量的数量。1.使用并查集判断图是否为连通的。2.任意选取一点,做 dfs 搜索,选取其中一个最远距离的点 A,再做一次 dfs,找到的所有距离最远的点以及点 A 都是 deepest root。考虑到为稀疏图,则使用动态链表#include#include#include#include
阅读全文
摘要:View Code并查集的题目也做的差不多了,关键还是理解find(),un()的过程……接着搜索一礼拜……#include<stdio.h>#define N 30009int f[N];int all[N];int up[N];int find(int pos){ if(f[pos]==-1) return pos; int temp; temp=f[pos]; f[pos]=find(f[pos]); up[pos]+=up[temp]; return f[pos];}void un(int a,int b){ int fa=find(a); int fb=find(b);
阅读全文
摘要:http://acm.nuaa.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1087思路:也是并查集,逆向思维,题目要求先把边所有边连起来,再去删; 那可以这样想,先(除去需要删的边)把边连起来(这里可以排序实现),在倒着执行操作,把删边当做连边操作即可一开始把前面的边保存起来,然后去掉后面为D的边,倒着执行D和P的操作(即遇到d,就可并a,b),答案倒着输出即可View Code #include<stdio.h>#include<iostream>#include<algorith
阅读全文
摘要:可以作为入门题练习,增加信心~~View Code #include<stdio.h>#define N 50005int f[N];bool v[N];int find(int pos){ if(f[pos]==-1)return pos; return f[pos]=find(f[pos]);}int un(int a,int b){ int fa=find(a); int fb=find(b); if(fa==fb)return 0; f[fa]=fb;return 1;}int main(){ int n,m,i,a,b,ca=1; while(scanf("%d
阅读全文
摘要:学习了种类并查集,又学了离散化STL里的map容器这几题里比较侧重对find()函数的理解View Code #include<iostream>#include<map>using namespace std;#define N 10005int f[N];int r[N];map<int,int>mm;int find(int pos){ if(f[pos]==-1) return pos; int t=f[pos]; f[pos]=find(f[pos]);//使f[pos]路径压缩,指向最终根节点 r[pos]=(r[pos]+r[t])%2;//r
阅读全文
摘要:把点与点的关系保存在连接矩阵里就好了,如果距离小于等于规定距离的话就赋值为1然后不断做(做符合条件)合并操作即可……View Code #include<stdio.h>#define N 1005int f[N];int d;int ji[N];struct data { int x,y;}p[N];bool map[N][N];int dis(data a,data b){ int temp=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); if(temp<=(d*d)) return 1; return 0;}int find(int p
阅读全文
摘要:这道题目,理解了好久,其实只要把关系图画一下,有些概念自然就知道了……当然也使我明白了,并查集因为通过路径压缩后,一个节点的find()过程,最多需要2次递归,最多一次修改……这样题目就理解了……View Code #include <stdio.h>#define max 50000+5int f[max];int r[max];/*rank[x]表示father[x]与x的关系rank[x] == 0 表示father[x]与x是同类rank[x] == 1 表示x吃father[x]rank[x] == 2 表示father[x]吃x*/void make_set(int x
阅读全文
摘要:View Code #include<stdio.h>#define N 2009int e[N];int f[N];int find(int pos){ if(f[pos]==-1)return pos; return f[pos]=find(f[pos]);}int un(int a,int b){ int fa=find(a),fb=find(b); if(fa==fb)return 0; f[fa]=fb;return 1;}int main(){ int t,n,m,rt,a,b,ca=0,i,T; scanf("%d",&T); t=T; w
阅读全文
摘要:这道题目oj比较奇怪,用g++提交可以,c++就不行了……思路:e[]保存敌人输入时:d,x,y时fx=find(x),fy=find(y)如果e[fx]==-1;e[fx]=fy否则 合并(e[fx],fy);对fy再做如上操作View Code #include<stdio.h>#include<iostream>using namespace std;#define N 100009int f[N];int e[N];int find(int pos){ if(f[pos]==-1)return pos; else f[pos]=find(f[pos]);}int
阅读全文
摘要:View Code #include<stdio.h>int f[30009];int find(int pos){ if(f[pos]==-1)return pos; return f[pos]=find(f[pos]);}int un(int a,int b){ int fa=find(a),fb=find(b); if(fa==fb)return 0; f[fa]=fb; return 1;}int main(){ int n,m,i,j,add,one,temp; while(scanf("%d%d",&n,&m),n||m) { for
阅读全文
|