1. 程式人生 > >NOIP2003 神經網路(bfs)

NOIP2003 神經網路(bfs)

NOIP2003 神經網路

題目背景:

人工神經網路(Artificial Neural Network)是一種新興的具有自我學習能力的計算系統,在模式識別、函式逼近及貸款風險評估等諸多領域有廣泛的應用。對神經網路的研究一直是當今的熱門方向,蘭蘭同學在自學了一本神經網路的入門書籍後,提出了一個簡化模型,他希望你能幫助他用程式檢驗這個神經網路模型的實用性。

題目描述:

在蘭蘭的模型中,神經網路就是一張有向圖,圖中的節點稱為神經元,而且兩個神經元之間至多有一條邊相連,下圖是一個神經元的例子:

神經元〔編號為1)

圖中,X1―X3是資訊輸入渠道,Y1-Y2是資訊輸出渠道,C1表示神經元目前的狀態,Ui是閾值,可視為神經元的一個內在引數。

神經元按一定的順序排列,構成整個神經網路。在蘭蘭的模型之中,神經網路中的神經無分為幾層;稱為輸入層、輸出層,和若干個中間層。每層神經元只向下一層的神經元輸出資訊,只從上一層神經元接受資訊。下圖是一個簡單的三層神經網路的例子。

蘭蘭規定,Ci服從公式:(其中n是網路中所有神經元的數目)

公式中的Wji(可能為負值)表示連線j號神經元和 i號神經元的邊的權值。當 Ci大於0時,該神經元處於興奮狀態,否則就處於平靜狀態。當神經元處於興奮狀態時,下一秒它會向其他神經元傳送訊號,訊號的強度為Ci。

如此.在輸入層神經元被激發之後,整個網路系統就在資訊傳輸的推動下進行運作。現在,給定一個神經網路,及當前輸入層神經元的狀態(Ci),要求你的程式運算出最後網路輸出層的狀態。

Input:

每組輸入第一行是兩個整數 nnn(1≤n≤1001≤n≤1001n100)和 ppp。接下來 nnn 行,每行兩個整數,第 i+1i+1i+1 行是神經元 iii 最初狀態和其閾值(UiU_iUi),非輸入層的神經元開始時狀態必然為 000。再下面 PPP 行,每行由兩個整數 iii,jjj 及一個整數 WijW_{ij}Wij,表示連線神經元 iii、jjj 的邊權值為 WijW_{ij}Wij

Output:

每組輸出包含若干行,每行有兩個整數,分別對應一個神經元的編號,及其最後的狀態,兩個整數間以空格分隔。僅僅輸出最後狀態大於零的輸出層神經元狀態,並且按照編號由小到大順序輸出!

若輸出層的神經元最後狀態均為 0,則輸出 NULL。

Sample Input:

5 6
1 0
1 0
0 1
0 1
0 1
1 3 1
1 4 1
1 5 1
2 3 1
2 4 1
2 5 1

Sample Output:

3 1
4 1
5 1

題解:

直接bfs就可以了,當從佇列裡面取出來一個點後,必然上一層的已經對它傳輸完。

這裡需要注意的是,起始點不會減去它的閥值。

 

程式碼如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;

const int N = 125,M = 4005;
int n,p,tot;
int U[N],in[N],out[N],head[N],vis[N];
long long c[N];

struct Edge{
    int u,v,next,w;
}e[M];

void adde(int u,int v,int w){
    e[++tot].u=u;e[tot].v=v;e[tot].w=w;
    e[tot].next=head[u];head[u]=tot;
}

int main(){
    scanf("%d%d",&n,&p);
    memset(head,-1,sizeof(head));memset(in,0,sizeof(in));memset(out,0,sizeof(out));tot=0;
    for(int i=1;i<=n;i++) scanf("%lld%d",&c[i],&U[i]);    
    for(int i=1,u,v,w;i<=p;i++){
        scanf("%d%d%d",&u,&v,&w);
        adde(u,v,w);
        out[u]++;in[v]++;
    }
    queue<int> q;
    for(int i=1;i<=n;i++) if(c[i]) q.push(i);
    memset(vis,0,sizeof(vis));
    while(!q.empty()){
        int u=q.front();q.pop();
        if(c[u]<=0) continue;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            c[v]+=e[i].w*c[u];
            if(!vis[v]){
                q.push(v);
                vis[v]=1;c[v]-=U[v];
            }
        }
    }
    int cnt = 0;
    for(int i=1;i<=n;i++){
        if(!out[i] &&c[i]>0){
            cnt++;
            printf("%d %lld\n",i,c[i]);
        }
    }
    if(!cnt) cout<<"NULL"<<endl;        
    return 0;
}