拓扑排序

拓扑排序:

不断取出入度为0的点,拓扑排序因此不唯一

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<algorithm>
using namespace std;
struct edge{
    int e,next;
    //double v;
};
edge edg[100005];
int n,m,head[105],in_degree[105],ans[105],cnt;
int main(){
    memset(head,-1,sizeof(head));
    cin>>n>>m;
    for(int i=0;i<m;i++){
       int a,b;
       cin>>a>>b;
       edg[i].e=b;
       edg[i].next=head[a];
       head[a]=i;
       in_degree[b]++;
       //num[i]=999999999999999;
    }
    queue<int>que;
    for(int i=1;i<=n;i++){
        if(in_degree[i]==0){
            que.push(i);
        }
    }
    while(!que.empty()){
        int temp=que.front();
        que.pop();
        ans[cnt++]=temp;
        if(cnt==n){
            for(int i=0;i<n;i++){
                cout<<ans[i]<<" ";
            }
            cout<<endl;
            return 0;
        }
        for(int i=head[temp];i!=-1;i=edg[i].next){
            int e=edg[i].e;
            in_degree[e]--;
            if(in_degree[e]==0){
                que.push(e);
            }
        }
    }
    cout<<"have loop"<<endl;
    //cout<<"orz"<<endl;
    return 0;
}

输出所有的拓扑排序

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,ans[105],in_degree[105],mark[105];
void func(int now,vector<vector<int> >edg){
    if(now==n+1){
        for(int i=1;i<=n;i++){
            cout<<ans[i]<<" ";
        }
        cout<<endl;
        return ;
    }
    for(int i=1;i<=n;i++){
        if(in_degree[i]==0&&mark[i]==0){
            ans[now]=i;
            mark[i]=1;
            for(int j=0;j<edg[i].size();i++){
                in_degree[edg[i][j]]--;
            }
            func(now+1,edg);
            for(int j=0;j<edg[i].size();j++){
                in_degree[edg[i][j]]++;
            }
            mark[i]=0;
        }
    }
}
int main(){
    //memset(head,-1,sizeof(head));
    cin>>n>>m;
    vector<vector<int> >edg(n+1,vector<int>());
    for(int i=0;i<m;i++){
       int a,b;
       cin>>a>>b;
       edg[a].push_back(b);
       in_degree[b]++;
       //num[i]=999999999999999;
    }
    func(1,edg);
    //cout<<"orz"<<endl;
    return 0;
}

题目描述
​ 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向,兰兰同学在自学了一本神经网络的入门书籍后,提出了一个简化模型,他希望你能帮助他用程序检验这个神经网络模型的实用性。

​ 在兰兰的模型中,神经网络就是一张有向图,图中的节点称为神经元,而且两个神经元之间至多有一条边相连,如果有一条边 X 的终点是第 i 号神经元,那么 X 即为该神经元的输入通道,如果有一条边 Y 的起点是第 i 号神经元,那么 Y 即为该神经元的输出通道,Ci 表示神经元目前的状态,Ui 是阈值,可视为神经元的一个内在参数。

​ 神经元按一定的顺序排列,构成整个神经网络。在兰兰的模型之中,神经网络中的神经元分为几层;称为输入层、输出层,和若干个中间层。每层神经元只向下一层的神经元输出信息,只从上一层神经元接受信息。

​ 兰兰规定,Ci 服从公式:

Ci=∑WjiCj−Ui ((j,i)∈E)
​ 公式中的 Wji(可能为负值)表示连接 j 号神经元和 i 号神经元的边的权值。当 Ci 大于 0 时,该神经元处于兴奋状态,否则就处于平静状态。当神经元处于兴奋状态时,下一秒它会向其他神经元传送信号,信号的强度为Ci。

​ 如此,在输入层神经元被激发之后,整个网络系统就在信息传输的推动下进行运作。现在,给定一个神经网络,及当前输入层神经元的状态(Ci),要求你的程序运算出最后网络输出层的状态。

输入
​ 输入文件第一行是两个整数 n(1≤n≤100) 和 p。接下来 n 行,每行 2 个整数,第 i+1 行是神经元 i 最初状态(Ci)和其阈值(Ui),非输入层的神经元开始时状态必然为 0。再下面 P 行,每行由 2 个整数 i,j 及 1 个整数Wij,表示连接神经元 i,j 的边权值为 Wij。

输出
​ 输出文件包含若干行,每行有 2 个整数,分别对应一个神经元的编号,及其最后的状态,2 个整数间以空格分隔。仅输出最后状态大于 0 的输出层神经元状态,并且按照编号由小到大顺序输出。

​ 若输出层的神经元最后状态均为 0,则输出 “NULL”。

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<algorithm>
using namespace std;
struct edge{
    int e,v,next;
};
edge edg[10005];
int n,m,c[105],u[105],head[105],in_degree[105],out_degree[105]
int main(){
    memset(head,-1,sizeof(head));
    cin>>n>>m;
    //vector<vector<int> >edg(n+1,vector<int>());
    queue<int>que;    
    for(int i=1;i<=n;i++){
       cin>>c[i]>>u[i];
       if(c[i]!=0){
           que.push(i);
       }
       //num[i]=999999999999999;
    }
    for(int i=0;i<m;i++){
        int a,b,v;
        cin>>a>>b>>v;
        edg[i].e=b;
        edg[i].v=v;
        edg[i].next=head[a];
        head[a]=i;
        in_degree[b]++;
        out_degree[a]++;
    }
    while(!que.empty()){
        int temp=que.front();
        que.pop();
        for(int i=head[temp];i!=-1;i=edg[i].next){
            int e=edg[i].e,v=edg[i].v;
            in_degree[e]--;
            if(c[temp]>0){
                c[e]+=v*c[temp];
            }
            if(in_degree[e]==0){
                que.push(e);
                c[e]-=u[e];
            }
        }
    }
    int f=0;
    for(int i=1;i<=n;i++){
        if(out_degree[i]==0&&c[i]>0){
            cout<<i<<" "<<c[i]<<endl;
            f=1;
        }
    }
    if(f==0){
        cout<<"NULL"<<endl;
    }
    //cout<<"orz"<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值