acm第11周总结

本文记录了作者在ACM学习过程中对并查集的理解与应用,通过解决具体题目,作者意识到并查集中kruskal算法的重要性,并在实践中发现代码细节的处理对结果的影响。同时,提到了在处理字符串问题时使用STL中map容器的经验,并分享了素数筛的模板代码。作者强调了主动学习、理解知识和专注力在学习过程中的价值。

这周主要是做了并查集的题,虽然并查集要比搜索简单,并且还有比较固定的模板,但是在做题的过程中感觉我对并查集的理解还有很多不到位的地方

在做p1396时卡住了,看了一下题解后找到了思路,发现这道题做不出来是对kruskal算法不是很理解,这道题因为已经对边权从小到大排序,所以小的先合并,大的后合并,所以只要在s与t联通时当前的拥挤度就是该路径最大拥挤度。

#include <bits/stdc++.h>
using 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<q2.w;
}
int main()
{
cin>>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<<q[i].w;
    break;
    }
}
    return 0;
}

在做p1892时感觉这道题并不难,但是明明感觉代码写的没有错,答案却就是不对,然后我定义了一个数组输出根节点测试了一下发现是因为有一个集合的根节点跑到n-2n的范围去了,也就是说在维护敌人的敌人就是朋友关系合并时应该将1-n范围内的值作为根节点,也就是说,merge(p+n,q)和merge(q+n,p)要与find函数中的father[find(x)]=find(y)相对应,虽然感觉做这道题花费了很长的时间很不应该,但这个错误让我发现了以前我所忽视的地方总归还是有所收获所以还是值得的

做p2256时不知道字符串类型的怎么处理,后看了题解,发现用到了stl中的map容器(很久没看stl的知识忘的差不多了之后要抽空复习一下),知道了用map容器剩下的也就简单了

#include<bits/stdc++.h>
using 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<string,int> 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."<<endl;
    else
    cout<<"No."<<endl;
    }
     return 0;
}

一部分简单的题因为基本上就是套模板所以能很容易写出来思路也很清晰

常见套路包括结构体的建立、结构体排序、合并时找最大值、合并时求和、找合并后集合个数等

但是也有一部分看起来简单的题自己敲的代码却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我在学习方法上的收获,首先就是不要为了考试而被动学习,这样学习起来会感觉非常枯燥乏味,很难坚持下去,而是应该把获取知识增强自己的实力作为学习的目标,这样才会主动去学习,也不会抗拒学习,考试反而能考的更好,再者就是我们身为理科生,对知识要注重理解而不是死记硬背,尤其是对于编程,死记代码更是不可取的,还有就是我们的精力都是有限的,所以如果分散精力干很多事情容易导致什么也干不好,所以应该选择自己心里最想干的一件事,然后专注的把这一件事干好,这样才不会一事无成。

 

 

 

 

 

 

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值