P1038 神经网络

复习图论系列。。。

这道题刚学OI的时候我就看过。被那个公式吓跑了。

其实那个公式也容易算嘛。

\(C_i = \sum_{(j,i) \in E}{W_{ji} \times C_j} - u_i\)

注意这个公式对输入层不适用!!!所以不管他的阈值。

我们用拓扑排序,从入度开始的来,用类似于刷表法的方法来更新所谓的\(C_i\)

整个神经网络分为三个部分:输入层(入度为0),中间层(一般的点)和输出层(出度为0)。

最终只需要输出那些出度为0的就好了。中间层不要输出!!!

里面说的那个神经冲动,其实就是C值。两者是一样的。

注意:只有当前C值大于0才能传递冲动给后面。

然后就没有了。

我天真的写了个反图。。。结果没用到。

代码:

#include<cstdio>
#include<queue>
const int maxn = 105, maxm = 20005;
struct Edges
{
    int next, to, weight;
} e[maxm], e2[maxm];
int head[maxn], tot, head2[maxn], tot2;
int indegree[maxn], outdegree[maxn];
int c[maxn], u[maxn];
int n, m;

void link(int u, int v, int w)
{
    e[++tot] = (Edges){head[u], v, w};
    head[u] = tot;
}
void link2(int u, int v, int w)
{
    e2[++tot2] = (Edges){head2[u], v, w};
    head2[u] = tot2;
}
void toposort()
{
    std::queue<int> q;
    for(int i = 1; i <= n; i++)
    {
        if(indegree[i] == 0 && c[i] > 0) q.push(i);
        else c[i] = -u[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(c[u] > 0) c[v] += e[i].weight * c[u];
            indegree[v]--;
            if(indegree[v] == 0) q.push(v);
        }
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d%d", &c[i], &u[i]);
    while(m--)
    {
        int u, v, w; scanf("%d%d%d", &u, &v, &w);
        link(u, v, w);
        indegree[v]++; outdegree[u]++;
    }
    toposort();
    bool flag = false;
    for(int i = 1; i <= n; i++)
    {
        if(!outdegree[i] && c[i] > 0) printf("%d %d\n", i, c[i]), flag = true;
    }
    if(!flag) printf("NULL\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Garen-Wang/p/9698489.html