#
题面指路 P1038 [NOIP2003 提高组] 神经网络
一眼图论
大家好像都是用的拓扑排序
看到公式之后感觉这道题挺适合反向建边来做

即,从输出层开始向输出层递归,每一个点在递归的时候都加上所有可以到达该点的神经返回的信号值(如果能返回的话
并进行了一些优化(因为一个点一旦输出信号值不是零就代表这个点已经跑过了,可以直接返回该点输出信号值)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const int maxN = 150;
const int maxE = (1e6+50);
struct Node{ int inn,oun; int val,u; }node[maxN];
int head[maxN]; int tot;
struct Edge{ int u,nxt,to,w; }edge[maxE];
void add_edge(int u,int v,int w){ edge[++tot].u = u; edge[tot].to = v; edge[tot].w = w; edge[tot].nxt = head[u]; head[u] = tot; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int Search(int k){ int eid = k; if(node[eid].val != 0) return node[eid].val; if(node[eid].inn == 0) return node[eid].val; for(int i = head[eid];i;i = edge[i].nxt){ int to_ = edge[i].to; int un = edge[i].u; int t = Search(to_); if(t <= 0) continue; node[un].val += t * edge[i].w; } node[k].val -= node[k].u; return node[k].val; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| int main(){ scanf("%d%d",&n,&p); for(int i = 1;i<=n;i++){ int sta,u; scanf("%d%d",&sta,&u); node[i].val = sta; node[i].u = u; node[i].oun = 0; node[i].inn = 0; } for(int i = 0;i<p;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); node[u].oun++;node[v].inn++; add_edge(v,u,w); } int flg = 1; for(int i = 1;i<=n;i++){ if(node[i].oun != 0) continue; int t = Search(i); if(t <= 0) continue; printf("%d %d\n",i,node[i].val); flg = 0; } if(flg) printf("NULL"); return 0; }
|
点此查看完整代码