这周的主要任务是学习拓扑排序,其次是补题,这个过程中的比较重要的stl是set在这里特别记录一下。然后记录这周学的最重要的算法。
一:set的用法
- 介绍
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的另外的应用。前提要求:这个一点要是有向无环图。
先介绍拓扑排序是怎样一步一步执行的吧
先看这个图,对于拓扑排序来说,我们要寻找入度为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;
}
完结撒花!!!!!