[NOIP2003提高组]神经网络

题目:洛谷P1038、Vijos P1105、codevs1088。

题目大意:给你一个有向图,每个非源点i的值的计算方式为$C_i=\sum\limits_{(j,i)\in E}W_{ji}C_j-U_i$,求每个汇点(没有出边的点)的值C。

解题思路:首先一遍DFS找出所有汇点,然后BFS计算即可。注意源点不需要减去U。

C++ Code:

#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
int n,w[222][222],p;
struct sj{
    int c,u;
}a[222];
vector<int>In,Out;
bool vis[222];
queue<int>q;
void dfs(int t){
    vis[t]=true;
    bool hasnxt=false;
    for(int i=1;i<=n;++i)
    if(w[t][i]){
        hasnxt=true;
        if(!vis[i])dfs(i);
    }
    if(!hasnxt)Out.push_back(t);
}
void bfs(){
    memset(vis,0,sizeof(vis));
    for(int i=0;i<In.size();++i){
        q.push(In[i]);
        vis[In[i]]=true;
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        bool b=true;
        a[u].c-=a[u].u;
        if(a[u].c>0)
        for(int v=1;v<=n;++v)
        if(w[u][v]){
            a[v].c+=w[u][v]*a[u].c;
            if(!vis[v]){
                vis[v]=true;
                q.push(v);
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&p);
    for(int i=1;i<=n;++i){
        scanf("%d%d",&a[i].c,&a[i].u);
        if(a[i].c)In.push_back(i);
    }
    memset(w,0,sizeof w);
    while(p--){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        w[x][y]=z;
    }
    memset(vis,0,sizeof vis);
    for(int i=0;i<In.size();++i)dfs(In[i]);
    for(int i=0;i<In.size();++i)a[In[i]].u=0;
    bfs();
    bool hasans=false;
    sort(Out.begin(),Out.end());
    for(int i=0;i<Out.size();++i)
    if(a[Out[i]].c>0){
        hasans=true;
        printf("%d %d\n",Out[i],a[Out[i]].c);
    }
    if(!hasans)puts("NULL");
    return 0;
}

 

posted @ 2017-08-21 17:34  Mrsrz  阅读(246)  评论(0编辑  收藏  举报