这题比较老,也比较简单,正好才学了链式前向星,练习食用。
众所周知,解决任何一道题只需要:
数据结构:链式前向星、优先对列
+算法:bfs拓扑排序
(个人对拓扑排序的理解:图、有先后关系、排序)
下面给出完整代码,数据结构和算法的应用通过代码中添加的注释讲解,比较详细,希望能帮到有需要的人
//P1038 神经网络 链式前向星+bfs拓扑排序+优先对列
#include <bits/stdc++.h>
using namespace std;
//链式前向星存储
const int NUM = 101;
struct Edge {
int to, next, w;
};
vector<Edge> edge;
int head[NUM] = {0};
int c[NUM], u[NUM];
//b布尔数组避免重复加入net对列(避免重复向下一层神经元发送信号)
bool b[NUM] = {false};
//添加新边
void addEdge(int l, int r, int w) {
Edge k;
k.to = r;
k.w = w;
k.next = head[l];
edge.push_back(k);
head[l] = edge.size() - 1;
}
//拓扑排序:函数返回优先队列,保证结果序号从小到大
priority_queue<int,vector<int>,greater<int> > out(queue<int> &net, int n) {
//小顶堆
priority_queue<int,vector<int>,greater<int> > ans;
int l, r;
while (net.size()) {
l = net.front();
net.pop();
//输出层,存入答案
if (!head[l]) ans.push(l);
//不满足条件,该神经元生涯结束
if (c[l] <= 0 || !head[l]) continue;
else {
for (int i = head[l]; i != 0; i = edge[i].next) {
r = edge[i].to;
if (!b[r]) {
net.push(r);
b[r] = true;
}
c[r] += c[l] * edge[i].w;
}
}
}
return ans;
}
int main() {
int n, p;
//小顶堆存答案
priority_queue<int,vector<int>,greater<int> > ans;
bool flag = false;
cin >> n >> p;
int l, r, w;
queue<int> net;
for (int i = 1; i <= n; i++) {
cin >> c[i] >> u[i];
if (c[i]) {
net.push(i);
b[i] = true;
} else c[i] -= u[i];
}
//填坑:读入边的起点为1
Edge k;
edge.push_back(k);
for (int i = 0; i < p; i++) {
cin >> l >> r >> w;
addEdge(l, r, w);
}
ans = out(net, n);
while (!ans.empty()) {
l = ans.top();
ans.pop();
if (c[l] > 0) {
flag = true;
cout << l << ' ' << c[l] << endl;
}
}
//如果没有输兴奋出层神经元,输出NULL
if (!flag) cout << "NULL";
}