[NOIP2003 提高组] 神经网络

题目背景

人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向,兰兰同学在自学了一本神经网络的入门书籍后,提出了一个简化模型,他希望你能帮助他用程序检验这个神经网络模型的实用性。

题目描述

在兰兰的模型中,神经网络就是一张有向图,图中的节点称为神经元,而且两个神经元之间至多有一条边相连,下图是一个神经元的例子:

神经元(编号为

i

i

i)

图中,

X

1

X

3

X_1 \sim X_3

X1​∼X3​ 是信息输入渠道,

Y

1

Y

2

Y_1 \sim Y_2

Y1​∼Y2​ 是信息输出渠道,

C

i

C_i

Ci​ 表示神经元目前的状态,

U

i

U_i

Ui​ 是阈值,可视为神经元的一个内在参数。

神经元按一定的顺序排列,构成整个神经网络。在兰兰的模型之中,神经网络中的神经元分为几层;称为输入层、输出层,和若干个中间层。每层神经元只向下一层的神经元输出信息,只从上一层神经元接受信息。下图是一个简单的三层神经网络的例子。

兰兰规定,

C

i

C_i

Ci​ 服从公式:(其中

n

n

n 是网络中所有神经元的数目)

C

i

=

(

(

j

,

i

)

E

W

j

i

C

j

)

U

i

C_i=\left(\sum\limits_{(j,i) \in E} W_{ji}C_{j}\right)-U_{i}

Ci​=

​(j,i)∈E∑​Wji​Cj​

​−Ui​

公式中的

W

j

i

W_{ji}

Wji​(可能为负值)表示连接

j

j

j 号神经元和

i

i

i 号神经元的边的权值。当

C

i

C_i

Ci​ 大于

0

0

0 时,该神经元处于兴奋状态,否则就处于平静状态。当神经元处于兴奋状态时,下一秒它会向其他神经元传送信号,信号的强度为

C

i

C_i

Ci​。

如此.在输入层神经元被激发之后,整个网络系统就在信息传输的推动下进行运作。现在,给定一个神经网络,及当前输入层神经元的状态(

C

i

C_i

Ci​),要求你的程序运算出最后网络输出层的状态。

输入格式

输入文件第一行是两个整数

n

n

n(

1

n

100

1 \le n \le 100

1≤n≤100)和

p

p

p。接下来

n

n

n 行,每行

2

2

2 个整数,第

i

+

1

i+1

i+1 行是神经元

i

i

i 最初状态和其阈值(

U

i

U_i

Ui​),非输入层的神经元开始时状态必然为

0

0

0。再下面

p

p

p 行,每行有两个整数

i

,

j

i,j

i,j 及一个整数

W

i

j

W_{ij}

Wij​,表示连接神经元

i

,

j

i,j

i,j 的边权值为

W

i

j

W_{ij}

Wij​。

输出格式

输出文件包含若干行,每行有

2

2

2 个整数,分别对应一个神经元的编号,及其最后的状态,

2

2

2 个整数间以空格分隔。仅输出最后状态大于

0

0

0 的输出层神经元状态,并且按照编号由小到大顺序输出。

若输出层的神经元最后状态均小于等于

0

0

0,则输出 NULL。

样例 #1

样例输入 #1

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

样例输出 #1

3 1

4 1

5 1

提示

【题目来源】

NOIP 2003 提高组第一题

思路分析

首先,本道题分为输入端和输出端,我们都知道,输入端的入度为0,输出端的出度为0,所以我们可以通过出度来判断是否为输出端其次,题目要求:

C

i

=

(

(

j

,

i

)

E

W

j

i

C

j

)

U

i

C_i=\left(\sum\limits_{(j,i) \in E} W_{ji}C_{j}\right)-U_{i}

Ci​=

​(j,i)∈E∑​Wji​Cj​

​−Ui​,由于

\sum

∑在括号里面,

U

i

U_{i}

Ui​在括号外边,因此我们可以预处理出

C

i

C_{i}

Ci​,这样方便些最后,处理完以上,我们就可以进行拓扑排序了,为什么用拓扑排序呢?因为这道题跟入度出度很有关系,而且本道题为有向图,关键还有就是传递的性质,这个时候我们就可以用拓扑排序来做了,细节:有的神经元不能传递,因此我们不能进行处理,就把它continue就可以了

代码

//如果出度为0,那么就为输出端

//拓扑排序铁定的了

#include

#include

#include

#include

using namespace std;

const int N = 210;

int e[N],ne[N],w[N],h[N],idx;

bool st[N];

int dist[N];

queue q;

int dou[N],din[N];

int c[N],u[N];//c为状态

int n,m;

void add(int a,int b,int c){

e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;

}

void topsort(){

while(q.size()){

int t=q.front();

q.pop();

if(c[t]<=0)continue;

for(int i=h[t];~i;i=ne[i]){

int j=e[i];

c[j]+=w[i]*c[t];

if(st[j])continue;

q.push(j);

st[j]=true;

}

}

}

int main(){

cin>>n>>m;

memset(h,-1,sizeof h);

for(int i=1;i<=n;i++){

cin>>c[i]>>u[i];

if(c[i]>0){

q.push(i);

st[i]=true;

}else{

c[i]-=u[i];

}

}

for(int i=1;i<=m;i++){

int a,b,c;

cin>>a>>b>>c;

add(a,b,c);

dou[a]++;

}

topsort();

bool f=true;

for(int i=1;i<=n;i++){

if(!dou[i]&&c[i]>0){

cout<

f=false;

}

}

if(f){

puts("NULL");

}

return 0;

}

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: