NC16679 神经网络 (拓扑排序)

题目:
  • 有向图,节点分为输入层(in[x]=0),输出层(out[x]=0),中间层。给出每个节点的参数c[i],u[i],其中除输入层外,其他节点的(c[i]=sum_{j=1}^{k}w_{j,i}*c[j]-u[i])。输出最后的输出层非零c[i],如果没有输出'NULL'。只有c[j]>0时,才会影响其所连下一层的点。
  • 拓扑排序,模拟一遍,从每一层传递下去。或者反向建图,再拓扑排序,再模拟。
// 模板省略
int n, m, T, t, p;
int head[N], cnt, num = 0;
int vis[N], cval[N], uval[N], out[N], in[N];
 
struct node
{
    int to;
    int c;
    int nxt;
}edge[N * 2];
 
queue<int>q;
 
inline void add(int u,int v,int w)
{
    edge[++cnt].to=v;
    edge[cnt].c=w;
    edge[cnt].nxt=head[u];
    head[u]=cnt;
}
 
void bfs(){
    int u;
    while(!q.empty()){
        u = q.front();
        q.pop();
        for(int i = head[u]; i ; i =edge[i].nxt){
            int v = edge[i].to;
            int w = edge[i].c;
            if(cval[u] > 0) cval[v] += w * cval[u];
            if(vis[v]) continue;
            vis[v] = 1;
            q.push(v);
        }
    }
}
 
int main()
{
    scanf("%d%d",&n,&p);
    for(int i = 1; i <= n; ++ i){
        scanf("%d%d",&cval[i],&uval[i]);
        if(!cval[i]) cval[i] = -1 * uval[i];
    }
    for(int i = 1; i <= p; ++ i){
        int x, y, z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        out[x] ++;
        in[y] ++;
    }
    for(int i = 1; i <= n; ++ i){
        if(!in[i]){
            q.push(i);
            vis[i] = 1;
        }
    }
    bfs();
    int flag = 0;
    for(int i = 1; i <= n; ++ i){
        if(!out[i] && cval[i] > 0){
            flag = 1;
            printf("%d %d
",i,cval[i]);
        }
    }
    if(!flag) printf("NULL
");
    return 0;
}
//
int n, m, T, p, top;
int head[N], cnt;
int cval[N], uval[N], in[N], out[N];
int q[N], h, t;
int vis[N];
 
struct node
{
    int to;
    int c;
    int nxt;
}edge[N * 2];
  
  
inline void add(int u,int v,int w)
{
    in[v] ++, out[u] ++;
    edge[++cnt].to=v;
    edge[cnt].c=w;
    edge[cnt].nxt=head[u];
    head[u]=cnt;
}
 
void topu(){
    int u;
    h = 1;
    while(h <= t){
        u = q[h];
        for(int i = head[u]; i; i = edge[i].nxt){
            int v = edge[i].to;
            if(vis[v]) continue;
            vis[v] = 1;
            q[++ t] = v;
        }
        h ++;
    }
}
 
void solve(){
    for(int i = t; i; -- i){
        int u = q[i], sum = 0;
        for(int j = head[u]; j; j = edge[j].nxt){
            int v = edge[j].to;
            int w = edge[j].c;
            if(cval[v] > 0) sum += w * cval[v];
        }
        if(out[u]) cval[u] = sum - uval[u];
    }
    int flag = 0;
    for(int i = 1; i <= n; ++ i){
        if(!in[i] && cval[i] > 0){
            flag = 1;
            printf("%d %d
",i,cval[i]);
        }
    }
    if(!flag) printf("NULL
");
}
 
 
int main()
{
    scanf("%d%d",&n,&p);
    for(int i = 1; i <= n; ++ i){
        scanf("%d%d",&cval[i],&uval[i]);
    }
    for(int i = 1; i <= p; ++ i){
        int x, y, z;
        scanf("%d%d%d",&x,&y,&z);
        add(y,x,z);         //反向建图
    }
    for(int i = 1; i <= n; ++ i){
        if(!in[i]) {
            q[++ t] = i;
            vis[i] = 1;
        }
    }
    topu();
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/A-sc/p/12862823.html