题目
根据题意建图属于一个有向图,
需要把图分层;
下一层的点的c值需要从上一层递推得出。
由于是有向无环图,就可以进行拓扑排序。
所得出的拓扑序列就可以满足这种层次顺序。
现在来简单科普一下拓扑排序。
拓扑排序
上图是一个有向无环图。
那么从一个点出发是不可能到达他自己本身的。
现在来介绍拓扑排序的步骤
1 将所有入度为0的节点入队
2 将节点出队,并将该节点所连的边删除,该边到达的节点的入度相应减一。
3 若有节点的入度减为0,将其入队。
4重复以上三步,直到队列为空。
基于以上操作,
本人发现了几点十分浅显的性质
性质1
节点i入队前,能到达它的节点一定都已经出队了。
性质2
若图中有环必定不能形成一个拓扑序。
言归正传
在进行拓扑排序的时候,就可以计算每个节点的c值。
上代码
#include<bits/stdc++.h>
using namespace std;
const int ll=1e4;
int n,p;
int head[ll],next[ll],ver[ll],wer[ll],tot;
int c[ll],u[ll],rd[ll],book[ll],cd[ll];
void add(int u,int v,int w){
tot++;
ver[tot]=v; wer[tot]=w;
next[tot]=head[u];
head[u]=tot;
}
int main(){
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++){
scanf("%d%d",&c[i],&u[i]);
book[i]=c[i];
}
for(int i=1;i<=p;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
rd[v]++;
cd[u]++;
}
queue <int> q;
for(int i=1;i<=n;i++)
if(book[i])
q.push(i);
while(q.size()){
int x=q.front();
if(!book[x])
c[x]-=u[x];
q.pop();
for(int i=head[x]; i ;i=next[i]){
int v=ver[i],w=wer[i];
if(c[x]>0)
c[v]+=w*c[x];
rd[v]--;
if(!rd[v]) q.push(v);
}
}
int flag=0;
for(int i=1;i<=n;i++)
if(c[i]>0&&!cd[i]){
cout<<i<<" "<<c[i]<<endl;
flag=1;
}
if(flag==0)
cout<<"NULL"<<endl;
return 0;
}