2021-02-02学习总结

2021-02-02学习总结

早上8:00学习打卡

早上9:00 – 14:00(5h)
学习并查集并且搞定题组
A - 一张桌子到底坐了几个人!

544的100大寿马上就要来临了,现在他要举办一场宴席,邀请了各路来宾前来祝寿。无奈的是,544的退休金并不是很多,因此需要尽可能使得宴席的桌数少。
但是544的朋友们也很挑剔,他们不会跟陌生人坐在一起,但是却可以跟朋友的朋友坐在一起。
具体来说,如果A认识B,B认识C,C认识D,E认识F,那么A,B,C,D可以坐在一起,E和F可以坐在一起,这样安排的桌数是2。显然,E或F不能与A,B,C,D坐在一起。
由于544已经100岁了,脑袋不足以支持太过复杂的运算,所以他邀请了你来解决这个问题:给出544的朋友之间的认识关系,请问最少需要摆多少张桌子呢?
Input
输入以一个整数T开始 (1<=T<=25) 表示测试数据组数. 接下来是T个测试数据。 每个测试数据以两个整数N和M开始(1<=N,M<=1000). N表示朋友的数目,编号为1~N。接下来是M行,每行包含两个整数A和B(A!=B),表示A和B互相是朋友。每两组测试数据间以一个空行相隔。
Output
对于每组测试数据,输出一个整数,代表最少需要摆放的桌数。
Sample Input
2
5 3
1 2
2 3
4 5
5 1
2 5
Sample Output
2
4

非常基础的并查集,因为我是看完啊哈算法的并查集,还有B站的正月点灯笼的视频,啊哈上的P200与这题是类似的,不能说完全不同,只能说是一模一样,上AC代码

#include<iostream>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<stdlib.h>
using namespace std;
int n,m,parent[100000];
void initialise()
{
	int i;
	for(i=1;i<=n;i++){
		parent[i]=i;
	}
}
int find_root(int x){//log(n);
	if(parent[x]==x)
		return x;
	else{
		//压缩路径
		parent[x]=find_root(parent[x]);
		return parent[x];
	}
}
void union_vertices(int x,int y){
	int  x_root = find_root(x);
	int  y_root = find_root(y);
	if(x_root!=y_root)
	{
		parent[y_root]=x_root;//靠左原则;
	}
}
int main()
{
	int i,x,y,T;
	cin>>T;
	while(T--){
		int cnt=0;
		cin>>n>>m;
		initialise();//初始化
		for(i=1;i<=m;i++){
			cin>>x>>y;
			union_vertices(x,y);
		}
		for(i=1;i<=n;i++){
			if(parent[i]==i){
				cnt++;
			}
		}
		printf("%d\n",cnt );
	}
}

B - 宝可梦到底有多少钉子!

代学长的宝可梦牧场中只有三种属性的宝可梦,水、火、草。这三种属性互相克制。(水克火,火克草,草克水)
现有N个宝可梦,以1-N编号,但是代学长并不知道每个宝可梦是什么属性。
孟学长调查了牧场之后,用两种说法对这N个宝可梦的属性进行描述:
第一种说法是"1 X Y",表示X和Y是同属性。
第二种说法是"2 X Y",表示X克Y。
孟学长对N个宝可梦,用上述两种说法,一句接一句地说出K句话,但是孟学长经常犯错,K句话有对有错。当一句话满足下列三条之一时,这句话就是错的,否则就是对的。
1) 当前的话与前面的某些对的话冲突,就是错的;
2) 当前的话中X或Y比N大,就是错的;
3) 当前的话表示X克X,就是错的。
孟学长每犯错一次就会收获一枚钉子,请根据给定的N(1 <= N <= 50,000)和K(0 <= K <= 100,000)句话,算出孟学长收获钉子的数量。
Input
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是属性。
若D=2,则表示X克Y。
Output
只有一个整数,表示钉子的数目。
Sample Input
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
Sample Output
3

ko no POKEMEN大师哒。
这题是我个人觉得三题里比较麻烦的,说说我的题解。
下标i表示i为水属性, i+n表示i为火属性, i+2 * n表示i为草属性,因为并不知道每个pokemen是个什么属性,所以需要假设。所以当x和y为同一属性的时候,把x,y和x+n,y+n和x+2n,y+2n合并成一个物种。
同理,当x克y时,把x,y+2n, x+2n和y+n,x+n和y合并;
在合并之前判断一下是否矛盾,
例如合并x,y之前判断一下x克y或y克x是不是存在。

然后,还没有写的同组的同学们,这题不是多组输入!!!
上AC

#include<iostream>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
int n,k,parent[300030];
void initialise()
{
    int i;
    for(i=1; i<=3*n; i++)
    {
        parent[i]=i;
    }
}
int find_root(int x) //log(n);
{
    if(x!=parent[x])
    {
        parent[x]=find_root(parent[x]);
    }
    return parent[x];
}
void union_vertices(int x,int y)
{
    int  x_root = find_root(parent[x]);
    int  y_root = find_root(parent[y]);
    parent[x_root]=y_root;
}
int main()
{
    //下标i表示i为水属性, i+n表示i为火属性, i+2*n表示i为草属性,因为并不知道每个pokemen是个什么属性,所以需要假设。
    int x,y,flag;
    scanf("%d%d",&n,&k);
    
        int cnt=0;
        initialise();//初始化
        while(k--)
        {
            scanf("%d%d%d",&flag,&x,&y);
            if(x>n||y>n)//2) 当前的话中X或Y比N大,就是错的;
                //3) 当前的话表示X克X,就是错的。
            {
                cnt++;
            }
            else
            {
                if(flag==1)//对关系1讨论
                {
                    if(find_root(x+n)==find_root(y)||find_root(x+2*n)==find_root(y))//如果x是y的克制或被克制,显然为谎言
                        cnt++;
                    else
                    {
                        union_vertices(x,y);
                        union_vertices(x+n,y+n);
                        union_vertices(x+2*n,y+2*n);
                        //如果为真,那么x的同类是y的同类,x的克制是y的克制,x的被克制是y的被克制
                    }
                }
                else
                {
                    if(x==y||find_root(x)==find_root(y)||find_root(x+2*n)==find_root(y))
                    {
                        cnt++;
                    }//如果1是2的同类或克制,显然为谎言
                    else
                    {
                        union_vertices(x,y+2*n);
                        union_vertices(x+n,y);
                        union_vertices(x+2*n,y+n);
                        如果为真,那么x的同类是y的克制,x的克制是y的同类,x的被克制是y的克制
                    }
                }
            }
            
        }
        printf("%d\n",cnt );
    
}

C - 撸猫到底会不会上瘾!
事实证明,撸猫是会上瘾的

不知从何时起,猫(Cat)已经开始成为一类校园新型毒品. 无数少女少男深受其害,一天不吸,浑身难受. 而就在最近,这种生物竟开始携带一种传染性极强的流行性病毒 —— 喵病毒 (Meow Viruses). 凡是接触猫的人,都极有可能感染喵病毒. 而我们一般称那些感染喵病毒的人,犯了喵病. 喵病的发病症状十分邪魔. 初期为连续性地疯狂撸猫,晚期甚至半夜爬上房顶学猫叫! 而由于喵病毒传染性极强,它已逐渐被认为是一种全球性的威胁. 为了减少传播给别人的机会, 最好的策略就是隔离可能的患者.
在Mr.蒟蒻的大学中,有许多学生团体. 同一个团体的学生经常彼此相通,一个学生可以同时加入几个团体. 为了防止喵病毒的传播,学校收集了所有学生团体的成员名单. 应对措施如下:
一旦一个团体中有一个患者,该团内的所有的成员就都可能是患者. 为了遏制这种病毒的传播,我们需要找到所有可能的患者. 现在已知编号为0的孟同学(感染源)已经犯了喵病,请你设计程序,找出所有可能的患者!
Input
输入文件包含多组数据,对于每组测试数据:
第一行依次为两个整数N和M, 其中N是学生的数量, M是学生团体的数量.
0 < N <=30000,0 <= M <= 500。
每个学生编号是一个0到N - 1之间的整数,一开始只有0号的孟同学被视为患者.
紧随的每一行是每一个团体的成员列表. 每行有一个整数K,代表成员数量. 之后有K个整数代表这个团体的学生. 一行中的所有整数由至少一个空格隔开. N = M = 0表示输入结束,不需要处理.
Output
对于每组测试数据, 一行输出一个正整数,即可能的患者数量。
Sample Input
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0
Sample Output
4
1
1

思路:用并查集来合并集合就可以了,把每个社团当作一个集合和并。最后,找出0号学生所在的集合的根节点,然后遍历所有学生,如果和0号学生的根节点相同,说明他们在一个集合当中。(0号学生真的是铁闸总)

#include<iostream>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<stdlib.h>
#include<cstdio>
using namespace std;
int n,m,parent[30010],rankk[30010];
void initialise()
{
	int i;
	for(i=0;i<=n;i++){
		parent[i]=i;
		rankk[i]=0;//不设置这个数组,树就会退化成链表
	}
}
int find_root(int x){//log(n);
	if(parent[x]==x)
		return x;
	else{
		parent[x]=find_root(parent[x]);
		return parent[x];
	}
}
void union_vertices(int x,int y){
	int  x_root = find_root(x);
	int  y_root = find_root(y);
	if(x_root!=y_root)
	{
		if(rankk[x_root]<rankk[y_root])
			parent[x_root]=y_root;//靠左原则;
		else{
			parent[y_root]=x_root;
			if(rankk[x_root]==rankk[y_root])
				rankk[x_root]++;//压缩路径
		}
	}
}
int main()
{
	int i,x,y,t;
	while(cin>>n>>m){
		if(n==0&&m==0)
			break;
		initialise();//初始化
		for(i=1;i<=m;i++){
			cin>>t>>x;
			for(int j=2;j<=t;j++){
				cin>>y;
			union_vertices(x,y);
		}
	}
		int cnt=1;
		for(i=1;i<=n;i++){
			if(find_root(i)==parent[0])//这个地方不一定是i的parent有可能是parent的parent,所以应该写成find_root(i)


			{
				cnt++;
			}
		}
		cout<<cnt<<endl;
	}
}

下午16:00-18:00(2h)
刷星火英语的四级卷子。

晚上19:30–21:00(1h30m)
答辩。
下面是阳神留给我的问题

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
using namespace std;
int a[4],book[4];
void dfs(int x){
	if(x==4){//全排列数组,起始等于末尾,说明已经产生了一种结果,进行输出。
		for(int i=1;i<=3;i++){
			cout<<a[i]<<" ";
		}
		cout<<endl;
		return;
	}
	for(int i=1;i<=3;i++){
		if(book[i]==0){
			a[x]=i;
			book[i]=1;
			dfs(x+1);//对后一个元素进行全排列
			book[i]=0;//回溯,book还原成未做的状态
		}
	}
	return;
}
int main(){
	memset(book,0,sizeof(book));
	dfs(1);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值