• Luogu P1038神经网络


    Description:

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

    神经元〔编号为111)
    图中,X1−X3X_1-X_3X1​−X3​是信息输入渠道,Y1−Y2Y_1-Y_2Y1​−Y2​是信息输出渠道,C1C_1C1​表示神经元目前的状态,UiU_iUi​是阈值,可视为神经元的一个内在参数。
    神经元按一定的顺序排列,构成整个神经网络。在兰兰的模型之中,神经网络中的神经元分为几层;称为输入层、输出层,和若干个中间层。每层神经元只向下一层的神经元输出信息,只从上一层神经元接受信息。下图是一个简单的三层神经网络的例子。
    兰兰规定,Ci​服从公式:(其中n是网络中所有神经元的数目)

    [C_i=∑_{j,i∈E}W_{ji}C_j−U_i ]

    [公式中的W_{ji}(可能为负值)表示连接j号神经元和i号神经元的边的权值。当 C_i​大于0时,该神经元处于兴奋状态,否则就处于平静状态。当神经元处于兴奋状态时,下一秒它会向其他神经元传送信号,信号的强度为C_i。 ]

    如此。在输入层神经元被激发之后,整个网络系统就在信息传输的推动下进行运作。现在,给定一个神经网络,及当前输入层神经元的状态(C_i​),要求你的程序运算出最后网络输出层的状态。

    Analysis:

    显然这道题用拓扑排序,我们从入度为0的点开始遍历,一直到出度为0的点。输入层神经元被激发之后,那么u[i]为1或0都没有关系,它一定会被激活。于是我们需要预处理这种情况,并预处理出度为0的点来方便输出。
    首先输入时确定是否为输入层(C[i]是否大于0),非输入层可以直接在这里减去U。根据公式,要求一个点的权值C,就要求出所有的C[j]*W[i,j],因为没有被激发的点的权值C为0,所以0乘W为0,因此不用计算。于是,所有的节点的权值是从他的上一个节点推过来的(拓扑排序),由于提前预处理了U,所以可以写成C[v] += C[u] * e[i].w,其中e[i]:u -> v。这样通过拓扑排序,C[i]的值便可以简单地累加起来了,避免了U的麻烦。

    Code

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define N 110
    #define P 100001
    using namespace std;
    struct edge{
    	int w,to,next;
    }e[P];
    int head[N],U[N],C[N],in[N],out[N],num_edge,n,p;
    inline void add(int u,int v,int w){
    	e[++num_edge].next = head[u];
    	e[num_edge].to = v;
    	e[num_edge].w = w;
    	head[u] = num_edge;
    }
    void topologicalSort(){
    	queue<int>Q;
    	for(int i = 1;i <= n;++i){
    		if(!in[i]){
    			Q.push(i);
    		}
    	}
    	while(!Q.empty()){
    		int u = Q.front();Q.pop();
    		for(int i = head[u];i;i = e[i].next){
    			int v = e[i].to;
    			if(!(--in[v])) Q.push(v);
    			if(C[u] > 0) C[v] += e[i].w*C[u];
    		}
    	}
    }
    void solve(){
    	topologicalSort();
    	bool tag = 1;
    	for(int i = 1;i <= n;++i){
    		// output 
    		if(C[i] > 0 && out[i] == 0){
    			 printf("%d %d
    ",i,C[i]);
    			 tag = 0;
    		}
    	}
    	if(tag) printf("NULL");
    }
    int main(){
    	scanf("%d%d",&n,&p);
    	for(int i = 1;i <= n;++i){
    		scanf("%d%d",&C[i],&U[i]);
    		if(C[i] == 0){
    			C[i] -= U[i];//?
    		}
    	}
    	for(int i = 1;i <= p;++i){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w);
    		++in[v];
    		++out[u];
    	}
    	solve();
    	return 0;
    }
    
    岂能尽如人意,但求无愧我心
  • 相关阅读:
    PL/SQL连接错误:ora-12705:cannot access NLS data files or invalid environment specified
    java 后台开发关键词解释
    架构、框架和设计模式关系(转)
    Web.xml配置详解
    SVN“验证位置时发生错误”的解决办法
    java遍历给定目录,树形结构输出所有文件,包括子目录中的文件
    android EditText 默认情况下不获取焦点(不弹出输入框)
    android listview item取消按点击效果
    如何实现可动态调整隐藏header的listview
    eclipse 启动到loading workbench... 自动关闭
  • 原文地址:https://www.cnblogs.com/Zforw/p/10651627.html
Copyright © 2020-2023  润新知