问题
在兰兰的模型中,神经网络就是一张有向图,图中的节点称为神经元,而且两个神经
元之间至多有一条边相连,下图是一个神经元的例子:
神经元〔编号为1)
图中,X1—X3是信息输入渠道,Y1-Y2是信息输出渠道,C1表示神经元目前的状态,
Ui是阈值,可视为神经元的一个内在参数。
神经元按一定的顺序排列,构成整个神经网络。在兰兰的模型之中,神经网络中的神
经无分为几层;称为输入层、输出层,和若干个中间层。每层神经元只向下一层的神经元
输出信息,只从上一层神经元接受信息。下图是一个简单的三层神经网络的例子。
兰兰规定,Ci服从公式:(其中n是网络中所有神经元的数目)
公式中的Wji(可能为负值)表示连接j号神经元和 i号神经元的边的权值。当 Ci大于0时,该神经元处于兴奋状态,否则就处于平静状态。当神经元处于兴奋状态时,下一秒
它会向其他神经元传送信号,信号的强度为Ci。
如此.在输入层神经元被激发之后,整个网络系统就在信息传输的推动下进行运作。
现在,给定一个神经网络,及当前输入层神经元的状态(Ci),要求你的程序运算出最后网络输出层的状态。
输入格式 Input Format
输入文件第一行是两个整数n(1≤n≤200)和p。接下来n行,每行两个整数,第i+1行是神经元i最初状态和其阈值(Ui),非输入层的神经元开始时状态必然为0。再下面P行,每行由两个整数i,j及一个整数Wij,表示连接神经元i、j的边权值为Wij。
输出格式 Output Format
输出文件包含若干行,每行有两个整数,分别对应一个神经元的编号,及其最后的状
态,两个整数间以空格分隔。仅输出最后状态非零的输出层神经元状态,并且按照编号由
小到大顺序输出!
若输出层的神经元最后状态均为 0,则输出 NULL。
分析
直接模拟就好了,也涉及不到什么特别高深的算法。对每个点计算其兴奋值。一开始想到了spfa,不行。因为它遍历的顺序存在问题,也就是说存在输入还没有输入完,就开始输出。这样显然是不对的。
我们想到了,要按照一定的顺序来遍历这些点,如何划分阶段呢?拓扑排序!每次找入度为零的点,然后删除它的初度,将它的值赋给与它临接的点。知道搜到最后一层,输出即可。
特别注意,一个点的c值如果不满足大于零,它不会对下个点传导兴奋。注意题目要求,一开始只有传入神经的c值不为零,所以我们完全可以将u的值加入c中,如果读入c=0则c付成-u,如果c<>0,则c付成c。也就是说传入神经不满足公式,这样就很好的解决了只有传入神经的数据。
以上这些只有在仔细分析题意之后才能得出。
反思
noip数据结构一般会停留在基础算法,不要只想着最短路,top排序,生成树等算法也要想一想。
仔细读题,多分析,只会算法的话不代表能够拿到分数,一定要注意隐含条件,注意题目要求,数据特点,可能错误等,不要急于代码!
code
program liukeke;
var
c:array[0..205] of longint;
into:array[0..205] of longint;
q:array[0..100000] of longint;
map,a:array[0..205,0..205] of longint;
i,n,p,cc,u,x,y,z,l,r,now:longint;
flag:boolean;
begin
readln(n,p);
for i:=1 to n do
begin
readln(cc,u);
if cc=0 then
c[i]:=-u
else
begin
c[i]:=cc;
inc(r);
q[r]:=i;
end;
end;
for i:=1 to p do
begin
readln(x,y,z);
map[x,y]:=z;
inc(a[x,0]);
a[x,a[x,0]]:=y;
inc(into[y]);
end;
l:=0;
while l<r do
begin
inc(l);
now:=q[l];
for i:=1 to a[now,0] do
begin
inc(c[a[now,i]],map[now,a[now,i]]*c[now]);
dec(into[a[now,i]]);
if (into[a[now,i]]=0)and(c[a[now,i]]>0) then
begin
inc(r);
q[r]:=a[now,i];
end;
end;
end;
flag:=true;
for i:=1 to n do
if (a[i,0]=0) and (c[i]>0) then
begin
flag:=false;
writeln(i,' ',c[i]);
end;
if flag then writeln('NULL');
end.