• 神经网络


    原题链接: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 }
  • 相关阅读:
    Docker 0x05: Dockerfile制作镜像
    Docker 0x04: Docker 基本使用
    Docker 0x03:Install Docker
    Docker 0x02: Docker生态
    Docker 0x01:Docker Container容器技术
    Axios发送AJAX请求
    Django学习之十三:提高页面开发效率减少冗余的模板系统
    javascript获取指定区间范围随机数
    完美解决eclipse编辑器中文字符过小问题
    mysql查询表所有列名,并用逗号分隔
  • 原文地址:https://www.cnblogs.com/OIerShawnZhou/p/7533106.html
Copyright © 2020-2023  润新知