神经网络

原题链接:https://www.luogu.org/problem/show?pid=1038#sub

翘了晚自习,在机房A掉了这道题。

其实这道题比较难看的是那个公式,有同学可能上来没能看明白(包括我也是

c[i] = w[i][j] * c[j] - u[i].  

如果是邻接表存图,把w[i][j]换成edge[i].dis就好。

注意到每层神经元只向下一层的神经元输出信息,只从上一层神经元接受信息,看图也能看明白,这是一个很显然的DAG,那么可以考虑拓扑排序。

对于那个u数组,这个玩意用处不大,而且除了公式也不参与计算,输入后可以直接把那个数减掉。

 使用拓扑排序的原因也很简单,如果你要算一个c[i],你需要先把之前那个c[j]算出来。题目要我们算终点(出度为0的点)的c值,那么就得先计算上一层,要计算上一层还得先计算上一层的上一层……最终,我们应该从第二层从上往下开始计算(第一层已经给出)。而这个计算的层次正好和拓扑排序方式相对应,所以考虑使用拓扑排序。

我喜欢用邻接表,读入的时候记录每个点的入度的出度,然后跑一次拓扑排序,排序的时候如果出现传递过程则更新c[i],直到排序完毕,我们就可以把最后面一层的c值算出来。

输出的时候判断,题目要输出c[i]>0的终点,照做就好了。输出的时候再加一个无输出标记,判断是不是输出NULL,就好了。

参考代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #define maxn 205
 6 #define INF 2147483647
 7 #define check cout << "ok" << endl;
 8 using namespace std;
 9 struct Edge{
10     int from,to,dis;
11 };
12 Edge edge[maxn];
13 int head[maxn];
14 int tot = 0;
15 int du_in[maxn];
16 int du_out[maxn];
17 int n,p;
18 int c[maxn],U[maxn];
19 int from,to,dis;
20 bool flag = false;
21 
22 void add_edge(int from,int to,int dis){
23     edge[++tot].from = head[from];
24     edge[tot].to = to;
25     edge[tot].dis = dis;
26     head[from] = tot;
27 }
28 
29 void toposort(void){
30     queue<int> q;
31     for (int i=1;i<=n;i++)
32         if (du_in[i] == 0)
33             q.push(i);
34     
35     while (!q.empty()){
36         int u = q.front();
37         q.pop();
38         if (c[u] <= 0){
39             for (int i = head[u];i!=0;i = edge[i].from){
40             int v = edge[i].to;
41             du_in[v]--;
42             if (du_in[v] = 0)
43                 q.push(i);    
44             }    
45             continue;
46         }
47         for (int i=head[u];i!=0;i = edge[i].from){
48             int v = edge[i].to;
49             c[v] += c[u] * edge[i].dis;
50             du_in[v]--;
51             if (du_in[v] == 0)
52                 q.push(v);
53         }
54         
55     }
56         
57 
58 }
59 
60 
61 int main(){
62     cin >> n >> p;
63     for (int i=1;i<=n;i++)
64         cin >> c[i] >> U[i];
65     for (int i=1;i<=n;i++)
66         if (c[i] == 0)
67             c[i] -=U[i];
68     
69     for (int i=1;i<=p;i++){
70         cin >> from >> to >> dis;
71         add_edge(from,to,dis);
72         du_in[to]++;
73         du_out[from]++;
74     }
75         
76     toposort();
77     
78     for(int i=1;i<=n;i++)
79         if(du_out[i]==0 && c[i]>0) {
80             cout << i << " " << c[i] << endl;
81             flag=true;
82         }
83     if(!flag) 
84         cout << "NULL";
85     return 0;
86 }

 

posted @ 2017-09-16 21:50  ShawnZhou_Aether  阅读(199)  评论(0编辑  收藏  举报