NOIP2003TG 神经网络 topo
神经网络 (network)
【问题背景】
人工神经网络( Artificial Neural Network )是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向,兰兰同学在自学了一本神经网络的入门书籍后,提出了一个简化模型,他希望你能帮助他用程序检验这个神经网络模型的实用性。
【问题描述】
在兰兰的模型中,神经网络就是一张有向图,图中的节点称为神经元,而且两个神经元之间至多有一条边相连,
下图是一个神经元的例子:
神经元〔编号为 1 )
图中, X1—X3 是信息输入渠道, Y1 - Y2 是信息输出渠道, C1 表示神经元目前的状态,
Ui 是阈值,可视为神经元的一个内在参数。
神经元按一定的顺序排列,构成整个神经网络。在兰兰的模型之中,神经网络中的神
经无分为几层;称为输入层、输出层,和若干个中间层。每层神经元只向下一层的神经元输出信息,只从上一层神经元接受信息。下图是一个简单的三层神经网络的例子 。
兰兰规定, C i 服从公式:(其中 n 是网络中所有神经元的数目)
公式中的 Wji (可能为负值)表示连接 j 号神经元和 i 号神经元的边的权值。当 Ci 大于 0 时,该神经元处于兴奋状态,否则就处于平静状态。当神经元处于兴奋状态时,下一秒
它会向其他神经元传送信号,信号的强度为 Ci 。
如此.在输入层神经元被激发之后,整个网络系统就在信息传输的推动下进行运作。
现在,给定一个神经网络,及当前输入层神经元的状态( Ci ),要求你的程序运算出最后网
络输出层的状态。
【输入格式】
输入文件第一行是两个整数 n ( 1≤n≤100 )和 p 。接下来 n 行,每行两个整数,第 i + 1 行是神经元 i 最初状态和其阈值( Ui ),非输入层的神经元开始时状态必然为 0 。再下面 P 行,每行由两个整数 i , j 及一个整数 Wij ,表示连接神经元 i 、 j 的边权值为 Wij 。
【输出格式】
输出文件包含若干行,每行有两个整数,分别对应一个神经元的编号,及其最后的状态,两个整数间以空格分隔。 仅输出最后状态大于0的输出层神经元状态,并且按照编号由小到大顺序输出!
若输出层的神经元最后状态均不大于0 ,则输出 NULL 。
【输入样例】
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
思路
坑爹的topo ,注意如何判断输出层以及如何更新每个点的状态
topo数组用来判断是否被删掉过,false表示已经被删掉,不存在
首先要知道如果当前节点没被激活就是c[i]<=0时,他的接收点j 的c[j] 的求和中不会包括 i
但是怎么处理减去阀值呢?
oo[i]=true表示更新I时,为第一次更新i ,这时要减去阀值 //相关:che
check表示当前删的点是不是输出层
代码
1 //note on the text by booble 2017.03.01 at dh 2 program network; 3 const 4 inf='network.in'; 5 outf='network.out'; 6 var 7 i,j,n,p,s,t,tmp,ok:longint; 8 check:boolean; 9 ru:array[1..100] of int64; //入度 10 u,c:array[1..100] of int64; //阀值和状态 11 w:array[1..100,1..100] of int64; //quanzhi! 12 pd:array[1..100,1..100] of boolean; //pd[i,j]=true表示i到j有边 13 topo,oo:array[1..100] of boolean; //oo[i]=true表示是第一次更新i 否则表示以前更新过 14 //topo数组用来判断是否被删掉过,false表示已经被删掉 15 procedure outgo; 16 begin 17 close(input); 18 close(output); 19 halt; 20 end; 21 22 procedure dotopo(i:longint); 23 var 24 check,che2:boolean; 25 begin 26 inc(ok); topo[i]:=false; //标记已经删除过 27 che2:=true; check:=false; 28 if c[i]<=0 then che2:=false; //che2=true时表示当前点是活跃的 29 for j:= 1 to n do //枚举i指向哪个j 30 if pd[i,j] then 31 begin 32 dec(ru[j]); //删边 33 if che2 then c[j]:=c[j]+w[i,j]*c[i]; //如果i是活跃的更新j的c 34 if oo[j] then begin //如果是第一次就减去阀值并且做标记 35 c[j]:=c[j]-u[j]; 36 oo[j]:=false; 37 end; 38 check:=true; 39 end; 40 if check then c[i]:=0; //只有更新过j的i才不在最后一层 41 end; 42 43 begin 44 45 assign(input,inf); 46 assign(output,outf); 47 reset(input); 48 rewrite(output); 49 readln(n,p); 50 fillchar(topo,sizeof(topo),true); 51 fillchar(oo,sizeof(oo),true); 52 for i:= 1 to n do 53 readln(c[i],u[i]); 54 55 for i:= 1 to p do 56 begin 57 readln(s,t,tmp); 58 inc(ru[t]); 59 w[s,t]:=tmp; pd[s,t]:=true; 60 end; 61 62 repeat 63 for i:= 1 to n do 64 if (ru[i]=0) and (topo[i]) then dotopo(i); 65 until ok=n; 66 67 for i:= 1 to n do 68 if c[i]>0 then begin 69 writeln(i,' ',c[i]); 70 check:=true; 71 end; 72 73 if check=false then writeln('NULL'); 74 75 outgo; 76 end.