这周的主要任务是学习拓扑排序,其次是补题,这个过程中的比较重要的stl是set在这里特别记录一下。然后记录这周学的最重要的算法。

一:set的用法 

  1. 介绍

set容器中的元素不会重复,当插入集合中已有的元素时,并不会插入进去,而且set容器里的元素自动从小到大排序。

即:set里面的元素不重复 且有序。

//头文件
#include<set>
//初始化定义
set<int>se;

set的不重复性插入在week10的比赛中运用的特别广泛,我们可以单单的插入一个数,那么写法就比较简单,直接set<int> s;就可以。

当然,我们也可以插入一个数组,在判断重复数组的时候运用广泛。写法为set<vector<int> > s;

运用插入函数s.insert() 还有s.size()大小函数,巧妙解题;

其他用法:

set<int> q;     //以int型为例 默认按键值升序
 set<int,greater<int>> p;  //降序排列 
 int x;
 q.insert(x);    //将x插入q中
 q.erase(x);        //删除q中的x元素,返回0或1,0表示set中不存在x
 q.clear();        //清空q
 q.empty();        //判断q是否为空,若是返回1,否则返回0
 q.size();        //返回q中元素的个数
 q.find(x);        //在q中查找x,返回x的迭代器,若x不存在,则返回指向q尾部的迭代器即 q.end()
 q.lower_bound(x); //返回一个迭代器,指向第一个键值不小于x的元素
 q.upper_bound(x); //返回一个迭代器,指向第一个键值大于x的元素q.rend();          //返回第一个元素的的前一个元素迭代器
 q.begin();          //返回指向q中第一个元素的迭代器q.end();         //返回指向q最后一个元素下一个位置的迭代器
 q.rbegin();         //返回最后一个元素

但是最重要的,还是如何去输出set里面的每一个数据呢?

for( set<int>::iterator i=q.begin();i!=q.end();i++) //set的遍历 
cout<<*i<<" ";

 这样就能够输出set里面的数据了

二:拓扑排序

其实拓扑排序在我看来不算是一种排序,而是结合dfs,bfs去进行数据的处理。排课表,合理安排工作等等。算是对dfs,bfs的另外的应用。前提要求:这个一点要是有向无环图。

先介绍拓扑排序是怎样一步一步执行的吧

Android Set 顺序输出 set排序_Android Set 顺序输出

 先看这个图,对于拓扑排序来说,我们要寻找入度为0的数字,一直找下去,知道剩下的都没有前驱,即入度都为零的时候。

例如图片里面,很明显只有1号前面没有横线,那么他就是我们要找的点,我们将他压入队列,压入队列之后就可以我们剪断1连接2,1连接3的横线,这时候发现2号没有前驱,那么压入队列,依次进行下去,直到最后。

那么,通常我们如何去判断有无前驱的,我们可以写函数来记录。而这个操作我们通常在建图的时候同时进行。

//写链表的模板 
   	for(int i=1;i<=m;i++){
   		int a,b;
   		cin>>a>>b;
   		g[a].push_back(b);
   		out[a]++;//出度++,最后只有最后的那些没有++,这一个细节在最后有记录 
   		ind[b]++;//记录入度,他是几说明他的头被几个数字连接到 
	   }

而对于更加深入的应用,可以看下面这道模板题

杂务 - 洛谷

这道是模板题,我将会和另外一道题对比,找一下细节。week10 - Virtual Judge

这两道题,其实从根本上说,其实也就一个地方不一样,杂物这道题说了,几个活动如果互不影响可以同时进行,而c题这个明确表示不可以。这就是差别,一个运用了拓扑,一个简单运用bfs

更加详细的解释,我在代码中讲解

杂物这道题:

#include<bits/stdc++.h>
using namespace std;
int n;
vector<int>g[10005];
int ind[10005];
int a[10005],f[10005]; 
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>i;
		cin>>a[i];
		int k;
		cin>>k;
		while(k!=0)
		{
			g[i].push_back(k);
			ind[k]++; 
			cin>>k;
		}
	}  //建图过程,这里就不多说了。 
	queue<int>q;
	for(int i=1;i<=n;i++)
	{
		if(ind[i]==0)
		{
			q.push(i);
			f[i]=a[i];
		}
	}//这里是找没有前驱的数字,意思就是找不需要准备工作的杂物 
	while(!q.empty())
	{
		int t=q.front();
		q.pop();
		for(int i=0;i<g[t].size();i++)
		{
			int u=g[t][i];
			ind[u]--;
			if(ind[u]==0)
			q.push(u);
			f[u]=max(f[u],f[t]+a[u]);//可以自己推导一下,一层层的互不干扰的要找最长的时间才行 
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		ans=max(ans,f[i]);
	}//不确定到底谁是最后一个没有前驱的,并且结果也是最小的 
	cout<<ans;
	return 0;	
}

另外那一道题:

using namespace std;
#define ll long long
int t[200005];
int k[200005];
vector<int> a[200005];
int used[200005]; 
ll n;
ll sum;
int main()
{
	queue<int>q;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>t[i]>>k[i];
		for(int j=1;j<=k[i];j++)
		{
			int x; 
			cin>>x;
			a[i].push_back(x);
		}
	}
	q.push(n);
	used[n]=1;
	while(!q.empty())
	{
		int s=q.front();
		q.pop();
		for(int i=0;i<a[s].size();i++)
		{
			if(used[a[s][i]]!=0)
			   continue;
			else
			{
				used[a[s][i]]=1;
				q.push(a[s][i]);
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(used[i]==1)
		{
			sum+=t[i];
		}
	}
	cout<<sum;
	return 0;
}

完结撒花!!!!!