这周主要是做了并查集的题,虽然并查集要比搜索简单,并且还有比较固定的模板,但是在做题的过程中感觉我对并查集的理解还有很多不到位的地方
在做p1396时卡住了,看了一下题解后找到了思路,发现这道题做不出来是对kruskal算法不是很理解,这道题因为已经对边权从小到大排序,所以小的先合并,大的后合并,所以只要在s与t联通时当前的拥挤度就是该路径最大拥挤度。
#includeusing namespace std; int father[40010]; int n,m,s,t; struct quyu { int u,v,w; }q[20010]; int find(int x) { return father[x]==x?x:father[x]=find(father[x]); } void merge(int x,int y) { if(find(x)!=find(y)) { father[find(x)]=find(y); } } bool cmp(quyu q1,quyu q2) { return q1.w >n>>m>>s>>t; for(int i=1;i<=m;i++) cin>>q[i].u>>q[i].v>>q[i].w; for(int i=1;i<=n;i++) father[i]=i; sort(q+1,q+m+1,cmp); for(int i=1;i<=m;i++) { merge(q[i].u,q[i].v); if(find(s)==find(t)) { cout< 在做p1892时感觉这道题并不难,但是明明感觉代码写的没有错,答案却就是不对,然后我定义了一个数组输出根节点测试了一下发现是因为有一个集合的根节点跑到n-2n的范围去了,也就是说在维护敌人的敌人就是朋友关系合并时应该将1-n范围内的值作为根节点,也就是说,merge(p+n,q)和merge(q+n,p)要与find函数中的father[find(x)]=find(y)相对应,虽然感觉做这道题花费了很长的时间很不应该,但这个错误让我发现了以前我所忽视的地方总归还是有所收获所以还是值得的
做p2256时不知道字符串类型的怎么处理,后看了题解,发现用到了stl中的map容器(很久没看stl的知识忘的差不多了之后要抽空复习一下),知道了用map容器剩下的也就简单了
#includeusing namespace std; int father[40000],s=0; int find(int x) { return father[x]==x?x:father[x]=find(father[x]); } void merge(int x,int y) { if(find(x)!=find(y)) { father[find(x)]=find(y); } } int main() { map mp; int n,m,k; string s,a,b; cin>>n>>m; for(int i=1;i<=n;i++) father[i]=i; for(int i=1;i<=n;i++) { cin>>s; mp[s]=i; } for(int i=1;i<=m;i++) { cin>>a>>b; merge(mp[a],mp[b]); } cin>>k; for(int i=1;i<=k;i++) { cin>>a>>b; if(find(mp[a])==find(mp[b])) cout<<"Yes."< 一部分简单的题因为基本上就是套模板所以能很容易写出来思路也很清晰
常见套路包括结构体的建立、结构体排序、合并时找最大值、合并时求和、找合并后集合个数等
但是也有一部分看起来简单的题自己敲的代码却A不了,看了题解发现并不是像自己想象的这么简单,这些题将并查集与其它的一些知识结合起来运用,例如:素数筛、01背包问题、搜索、stl
了解了一下我之前没见过的素数筛,素数筛就是用筛选的方法筛去不是素数的正整数(也就是合数)
素数筛模板:
int primes[N], cnt; // primes[]存储所有素数 2 bool st[N]; // st[x]存储x是否被筛掉 3 4 void get_primes(int n) 5 { 6 for (int i = 2; i <= n; i ++ ) 7 { 8 if (!st[i]) primes[cnt ++ ] = i; 9 for (int j = 0; primes[j] <= n / i; j ++ ) 10 { 11 st[primes[j] * i] = true; 12 if (i % primes[j] == 0) break; 13 } 14 } 15 }最后写一下跟着费老师学了快一个学期的acm我在学习方法上的收获,首先就是不要为了考试而被动学习,这样学习起来会感觉非常枯燥乏味,很难坚持下去,而是应该把获取知识增强自己的实力作为学习的目标,这样才会主动去学习,也不会抗拒学习,考试反而能考的更好,再者就是我们身为理科生,对知识要注重理解而不是死记硬背,尤其是对于编程,死记代码更是不可取的,还有就是我们的精力都是有限的,所以如果分散精力干很多事情容易导致什么也干不好,所以应该选择自己心里最想干的一件事,然后专注的把这一件事干好,这样才不会一事无成。



