写在读前:坑点略多,但数据量较小;
此题解仅代表笔者的一己之见,若有所偏差或失误请读者多多指出并加以海涵;
若您有更好的理解及方法欢迎在评论区分享高见共同讨论。
先上题目地址请移步洛谷;
题目(题目截图用于学习):



输入:
5 6
1 0
1 0
0 1
0 1
0 1
1 3 1
1 4 1
1 5 1
2 3 1
2 4 1
2 5 1
输出:
3 1
4 1
5 1
题目分析与算法设计:
先说题目中的Ci和Ui,Ci与Ui包括边权都可以为0为负,但值得一提的是题目中所给的“输入层”一开始就处于活跃状态,即“输入层”的Ui就不用管了233333 ;
再来说“传输层”,“传输层”只有当接收到的能量突破阈值(即使Ui>0)的时候,才可以处于活跃状态,具有往下传输能力。

而这个公式,意即当轮到这个结点传输能量时,其具有的能量是上一层与它相连的所有结点的(C值乘以相连路径权值)的和,当然,如果上一层某个结点没有处于活跃态(即C值小于等于0),就不能传输能量,便不用纳入计算。
说一个处理的技巧,在输入结点的初始状态时,将该点的C值设为-U,这样后续就可以直接拿C来计算,不用管U值了,因为U值的作用即根据接收到的能量能否突破阈值来判断该点能否处于活跃态,而这样处理便可以等价转换为依据C是否大于0判断该点是否处于活跃态。当然,“输入层”的结点本身就处于活跃态,便可以不做处理。
题目看起来比较复杂,细节较多,但核心算法只有一个拓扑:
从输入层开始bfs图,遇到入度为0的点加入队列,遇到输出层且活跃(即出度为0,C值大于0)的点加入答案队列;
数据结构:
在储存图时笔者采用了后续处理起来比较方便的向前星,不了解的读者可以参考这篇博客,在前半段有向前星的详细讲解;
在储存入度为0的结点时使用的是具有三个参数(i,Ci,Ui)的queue队列,在储存答案时使用的是vector(参数同上)数组;
struct node1{
int num;
int ui,ci;
};
node1 a[105];
模块设计、分块讲解:
初始化、读入与预处理:
使用先前星储存图,将除“输入层”外每个结点的U值转移到C值上,并且构建最初的拓扑队列;
for(int i=1;i<=n;i++){
//a为结点信息
scanf("%d%d",&a[i].ci,&a[i].ui);
a[i].num=i;
if(a[i].ci==0) a[i].ci-=a[i].ui; //对除输入层以外结点做“转移操作”
}
for(int num=0;num<m;num++){
//向前星储存图
int u

本文是关于NOIP提高组2003年神经网络问题的题解,重点讨论了如何利用拓扑排序和向前星数据结构解决题目中涉及的算法问题。在分析中,提到了输入层和传输层的处理技巧,以及如何初始化、读入数据、预处理和构建拓扑队列。文章还给出了完整的代码实现,并强调了答案输出的排序要求。
最低0.47元/天 解锁文章
347

被折叠的 条评论
为什么被折叠?



