Luogu P1038 神经网络 (拓扑排序模版)

qwq

拓扑排序模板题。

拓扑排序,是在一个$DAG$中,其拓扑排序为其所有结点的一个线性排序(答案不唯一)。

该排序满足这样的条件——对于图中的任意两个结点$u$和$v$,若存在一条有向边从$u$指向$v$,则在拓扑排序中$u$一定出现在$v$前面。

就好比一张流程图,必须完成这一步之前的所有步骤才能进行这一步。

代码实现:记录入度,每次走过一条边$(u,v)$将$v$的入度-1,入度为0时加入队列。

对于这道题,判断某个神经元是否兴奋(能继续传递)必须先走过到达这个神经元的每一条神经,恰好满足拓扑排序的定义。

注意:对于一个状态为负的神经元,需要将它的状态清零后加入队列(这样对后面不会有影响),否则如果不加入队列它后面点的入度没办法清零。

代码如下

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
#include<queue>
const int maxn = 1005;
queue <int> q;
priority_queue < pair<int,int>,vector < pair<int,int> >,greater < pair<int,int> > > ans;
int n,p,x,y,z,cnt;
int c[maxn],u[maxn],in[maxn];
int to[maxn],head[maxn],nxt[maxn],val[maxn];


void add(int x,int y,int z){
    to[++cnt] = y;
    nxt[cnt] = head[x];
    head[x] = cnt;
    val[cnt] = z;
}

void topo(){
    for(int i = 1;i <= n;i++)
        if(!in[i])q.push(i);
    while(!q.empty()){
        int x = q.front();
        q.pop();
        if(!head[x])
            if(c[x]>0) ans.push( make_pair(x,c[x]));
        for(int i = head[x];i;i = nxt[i]){
            int y = to[i];
            in[y]--;
            c[y] += c[x]*val[i];
            if(!in[y]){
                c[y] -= u[y];
                if(c[y]<0) c[y] = 0;
                q.push(y);
            }
        }
    }
}

int main(){
    scanf("%d%d",&n,&p);
    for(int i = 1;i <= n;i++)
        scanf("%d%d",&c[i],&u[i]);
    for(int i = 1;i <= p;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        in[y]++;
    }
    topo();
    if(ans.empty()){
        printf("NULL");
        return 0;
    }
    while(!ans.empty()){
        printf("%d %d
",ans.top().first,ans.top().second);
        ans.pop();
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/mogeko/p/10786405.html