本周学习总结

近两周学习了并查集和拓扑排序。课上老师讲了具体的实现思想,并且通过题目直观地感受了并查集和拓扑排序的应用。

并查集:

并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。并查集模板主要由一个整型数组pre[ ]和两个函数find( )、join( )构成。

数组 pre[ ] 记录了每个点的前驱节点。

for(int i=0;i<n;i++)//n表示输入的结点个数
{pre[i]=i;//将每一个结点的前导点设为自己
}

函数 find(x) 用于查找指定节点 x 属于哪个集合。路径压缩为了加快查找速度,将x点与其根节点直接相连,构造成类似于只有叶子结点没有分支的树

int find(int x)
{while(pre[x]!=x)
    x=pre[x];
    int i=x, j;
 while(i!=x)//路径压缩算法
{   j=pre[i];//记录x前导结点
    pre[i]=x;//将i的前导结点设置为x根节点
    i=j;
}
    return x;
}

函数 join(x,y) 用于合并两个节点 x 和 y 。

void join(int x,int y)
{int a=find(x);//x的根节点为a
 int b=find(y);//y的根节点为b
 if(a!=b)//a,b不是相同根节点,说明ab不连通
{pre[a]=b;//将ab相连,将a的前导结点设为b
}
}

例题:P1195 口袋的天空 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

N个云朵,M个关系,云朵通过代价L连成K棉花糖,一个棉花糖至少需要一个云朵,输出最小代价。

首先让我们选k朵云做棉花糖,换句话说就是选K个节点构造最小生成树。全部n个点的最小生成树有(n-1)条边,那选k个节点就是(n-k)条边。一共就m条边,如果都选完了还没有选出(n-k)条边来,就是No Answer了。

#include<iostream>
#include<algorithm> 
using namespace std;
struct woyaohongming{
	int s,e,w;    //s,w代表边上的两个节点,w权值费用
}a[200005];
int pre[200005];  //并查集用的f数组
bool cmp(woyaohongming a,woyaohongming b){   //sort排序规则,按费用从低到高排序
	return a.w<b.w;
}
int find(int a){  //并查集的“找祖宗”函数,路径压缩
	if(pre[a]==a)
	return a;
	else return pre[a]=find(pre[a]);
}
int main(){
	int n,m,k;
	cin>>n>>m>>k;  

	for(int i=1;i<=n;i++)   
	pre[i]=i;  //并查集数组初始化,每个节点的祖宗一开始是它自己

	for(int i=1;i<=m;i++)
	cin>>a[i].s>>a[i].e>>a[i].w;  //输入图的信息

	sort(a+1,a+1+m,cmp);   //快活的按权值排个序
   int cnt=0,sum=0;        //cnt是已经选中的边数,sum是最终要输出的最小权值
	for(int i=1;i<=m;i++){   //m条边,循环m次
		if(find(a[i].s)!=find(a[i].e)){ //如果俩节点的祖宗不相等(也就是不是回路),就可以加进去
			pre[find(a[i].s)]=find(a[i].e); //把它俩合并成一个祖宗
			sum+=a[i].w;                    //更新最小费用
			cnt++;                          //边数+1
		}
		if(cnt>=n-k)        //边数到达(n-k)条边,任务完成,break
		break;
	}
	if(cnt>=n-k)    
	cout<<sum;      //输出最小权值
	else cout<<"No Answer";  
	return 0; 
} 

拓扑排序:

在一个有向图中,对所有结点进行排序,要求没有一个节点指向它前面的节点。先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点的入度减一。一直做改操作,直到所有的节点都被分离出来。如果最后不存在入度为0的节点,那就说明有环,不存在拓扑排序。

本周看的拓扑排序的内容不算太多,主要看了上课讲的拓扑排序的例题,还是有点不太理解,总之能总结的内容不多。而且,下星期要开始以看题做题了,会多看一下关于此方面的内容,加强对拓扑排序算法的理解和应用。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值