先来说一下,对这个课的感受,学习到了什么:在大学里一直是一个比较自律的人,即使在学习能力相对较弱的情况下,还是义无反顾的选择了这门课,上大学以前谁能想到我曾经是一个对游戏极度痴狂的人,上大学以后顿悟了,从那一刻开始到现在我一直在建立一个基础薄弱的新的体系,一个能让我看到光明的新体系,用于摆脱过去的旧模式(每天只想着游戏),建立一个与过去完全不同的体系,可想而知这个过程必定是艰难的,首先就表现在对知识开始学习的困难,慢,效率极低,入门难于其他人,就上学期的程序设计而言,我用来写代码的时间特别多,但这仅仅是刚达到其他同学用较短时间完成的任务量,也没能达到老师的要求,我知道这是我当下能力的表现,但我始终坚信积累多了会变得和以前不一样、一切会好起来,在寒假的时候,我也在一点点的改变自己,把洛谷上的题接着往下做,我只能通过这种方式来进行学习,如果不通过这个方式,对那个时候极不稳定的体系就会崩塌,收益降低,所以我只能一点点的建立、一点点的改变,大一下学期开学后,再回看大一上学期切实的感受到了自己真的不一样了,选择这门课后,我其实就知道以我当下之能力,我根本无法很好的结束课程的学习和得不到一个好的睡眠,但就是想试一试,就是试一试,课开始后我也切实的感悟到费老师的觉悟之高,也深深感染了我,现在也建立起一个了解别人的思路(看资料和看题解)-写博客督促自己-自己做题,这种方式进行学习。要问我学到了什么,除了知识以外,也说不清自己哪里改变(我认为短期是难以改变我自己的,但学了改变的方法以后,虽对当下影响微乎其微,但我相信在日后定会迸发新的生机),感觉一切都往好的方向发展,也促进了我新体系的建立,为以后的学习积攒了力量。学这门课对我来说,虽降低学分绩点,但提高了人生高度。
总结:这一个星期我把上个星期看的几道题全做完了,另外又多做了一些没看的题,涉及的题没有拓扑排序的,全做了一些并查集的简单题,算是吧。
做的题虽简单但是我还是想分享几道题:
1、P2814 家谱 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意:输入多行字符串,一系列有关父子关系的描述,#name为父亲,下面带着若干字符串+name为儿子,再接下来?name代表求该人最早的祖先,如果遇到$代表结束。
思路:存储数据是关键,用map存储即可,处理好数据后,初始化,将父亲与孩子相连,然后查找给定人的祖先。
以下是我写的代码,可以说map真的是好用。
#include<bits/stdc++.h>
using namespace std;
string a,b;
map<string,string> c;
map<int,string> d;
map<int,char> e;
char f;
int g,h;
map<int,string> m;
string find(string s){
return c[s]==s?s:c[s]=find(c[s]);
}
int main(){
while(1){
cin>>f;
if(f=='$') break;
cin>>a;
if(f=='#'||f=='+'){
e[++g]=f;
d[g]=a;
}
else
m[++h]=a;
}
for(int i=1;i<=g;i++)
c[d[i]]=d[i];
for(int i=1;i<=g;i++){
if(e[i]=='#')
b=d[i];
else
c[d[i]]=b;
}
for(int i=1;i<=h;i++){
cout<<m[i]<<" "<<find(m[i])<<endl;
}
return 0;
}
2、P2256 一中校运会之百米跑 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意:共有N个参赛选手,给你选手的名字,m句话告诉你那俩同学一组,老师问你k句话,问你俩人是否一组,如果一组输出Yes.,否则输出No.。
思路:使用map对并查集根节点进行初始化,把给的每两个结点并起来,再进行寻找给予两个人的根节点是否相同,如果相同输出Yes.,否则输出No.。
这道题存数据也是关键。
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
map<string,string> ma;
string x,y;
string find(string s){
return ma[s]==s?s:ma[s]=find(ma[s]);
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>x;
ma[x]=x;
}
for(int i=1;i<=m;i++){
cin>>x>>y;
string fx=find(x),fy=find(y);
if(fx!=fy) ma[fx]=fy;
}
cin>>k;
for(int i=1;i<=k;i++){
cin>>x>>y;
string fx=find(x),fy=find(y);
if(fx==fy) cout<<"Yes."<<endl;
else
cout<<"No."<<endl;
}
}
3、P2661 [NOIP2015 提高组] 信息传递 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意:有n个同学正在玩信息传递游戏,每个人有一个固定的信息传递对象,编号为i的同学的信息传递对象是编号为Ti的同学,游戏开始每个人都只知道自己的生日,之后每一轮,所有人会同时将自己当前所知的信息告诉各自的信息传递对象,当有人从别人口中得知自己的生日时游戏结束,问该游戏可以进行几轮。
思路:
先用并查集判断是否构成一个环,如果是的话,我们就可以记录下这个答案,然后是最小的答案。那么,如果构成一个环的话,怎么记录它的长度呢?我们可以先定义一个临时变量sum,在并查集找祖先的函数中使cnt的值加1,最后函数结束时就能得到这个环的长度了,同时,如果构成了一个环,就不需要把这个环的结尾接上,否则会陷入死循环!
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int n, fa[N], sum= 0x3f3f3f3f;
int find(int x, int &cnt) {
sum ++;
if (fa[x] == x) return x;
else return find(fa[x], cnt);
}
int main () {
scanf("%d", &n);
for (int i = 1; i <= n; i ++)
fa[i] = i;
for (int i = 1; i <= n; i ++) {
int sum= 0, f;
scanf("%d", &f);
if (find(f, cnt) == i) {
sum= min(ans, sum);
}else
fa[i] = f;
}
printf("%d", sum);
return 0;
}
现在我所涉及到的并查集,就是单纯的合并,寻找祖先结点,如何更好存数据、生成最小树等问题,现在慢慢提高,在接下来的几周希望可以学到更多东西。