D152 拓扑排序 P1038 [NOIP 2003 提高组] 神经网络
D152 拓扑排序 P1038 [NOIP 2003 提高组] 神经网络_哔哩哔哩_bilibili
P1038 [NOIP 2003 提高组] 神经网络 - 洛谷
一个分层的有向无环图,n 个点,m 条边,每个点都有两个属性 $C_i$ 和 $U_i$,传递关系 $C_i=(\sum{W_{ji}*C_j})-U_i,\;C_j>0$,求输出层的 $C_i>0$ 的点

思路
既然是研究有向无环图的传递问题,自然是拓扑排序,如何建图呢?
除了记录入度数组,还要记录出度数组,用来判是否输出层的点,因为输出层的出度 $=0$
在拓扑开始时,把输入层的点均入队,其他层的点先减去阈值 $U_i$
然后,跑拓扑排序,累计各点的 $C_i$ 值。最后,按条件输出
相关板子:
// 拓扑排序 O(n) #include<bits/stdc++.h> using namespace std; const int N=105; vector<pair<int,int>> e[N]; int n,m; int C[N],U[N],rd[N],cd[N]; void topo(){ queue<int> q; for(int i=1; i<=n; i++){ if(rd[i]==0) q.push(i); //输入层的点均入队 else C[i]-=U[i]; //其他层先减阈值Ui(点权) } while(!q.empty()){ int u=q.front(); q.pop(); for(auto [v,w]:e[u]){ if(C[u]>0) C[v]+=C[u]*w; //如果u点能兴奋,则向v点发送信号C[u] if(--rd[v]==0) q.push(v); } } } int main(){ cin>>n>>m; //n个神经元 m条边 for(int i=1;i<=n;i++) cin>>C[i]>>U[i]; //每个点的最初状态和阈值 for(int i=1,u,v,w; i<=m; i++){ cin>>u>>v>>w; //从点u到点v的边权w e[u].emplace_back(v,w); cd[u]++; //u的出度+1 rd[v]++; //v的入度+1 } topo(); bool ok=0; for(int i=1;i<=n;i++)if(!cd[i]&&C[i]>0){ //如果是输出层且状态>0的点 cout<<i<<" "<<C[i]<<"\n",ok=1; } if(!ok) cout<<"NULL"; }
浙公网安备 33010602011771号