题目来源https://www.luogu.org/problem/show?pid=1038
拓扑排序。对入度为0的点操作,若该点的状态值<0,则只删除其出边。
若状态值>0,则先对其指向的节点处理,更新其状态值,再删除出边
分层处理。将产生的新的入度为0的节点放入队列中
#include <algorithm>
#include <iostream>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <cctype>
#include <vector>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
int c[101];
int f[101];
struct edge{int t,w;};
vector<edge> v[101];
int du[101]={0};
bool vis[101]={0};
int main()
{
ios::sync_with_stdio(false);
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x,y;cin>>x>>y;
c[i]=x;f[i]=y;
}
for(int i=1;i<=m;i++)
{
int x,y,z;cin>>x>>y>>z;
edge l;l.t=y;l.w=z;
v[x].push_back(l);
du[y]++;
}
queue<int> q,p;
vector<int> ans;
for(int i=1;i<=n;i++)if(du[i]==0)q.push(i);
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=1;
if(v[u].size()==0)ans.push_back(u);
for(int i=0;i<v[u].size();i++)
{
if(!vis[v[u][i].t])
{
du[v[u][i].t]--;
if(c[u]>0)c[v[u][i].t]+=v[u][i].w*c[u];
if(!du[v[u][i].t])
{
p.push(v[u][i].t);
c[v[u][i].t]-=f[v[u][i].t];
}
}
}
if(q.empty())swap(p,q);
}
sort(ans.begin(),ans.end());
int ok=0;
for(int i=0;i<ans.size();i++)if(c[ans[i]]>0){ok=1;break;}
if(!ok)cout<<"NULL";
else
{
for(int i=0;i<ans.size();i++)if(c[ans[i]]>0)cout<<ans[i]<<" "<<c[ans[i]]<<endl;
}
return 0;
}