题目:
- 有向图,节点分为输入层(in[x]=0),输出层(out[x]=0),中间层。给出每个节点的参数c[i],u[i],其中除输入层外,其他节点的(c[i]=sum_{j=1}^{k}w_{j,i}*c[j]-u[i])。输出最后的输出层非零c[i],如果没有输出'NULL'。只有c[j]>0时,才会影响其所连下一层的点。
- 拓扑排序,模拟一遍,从每一层传递下去。或者反向建图,再拓扑排序,再模拟。
// 模板省略
int n, m, T, t, p;
int head[N], cnt, num = 0;
int vis[N], cval[N], uval[N], out[N], in[N];
struct node
{
int to;
int c;
int nxt;
}edge[N * 2];
queue<int>q;
inline void add(int u,int v,int w)
{
edge[++cnt].to=v;
edge[cnt].c=w;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
void bfs(){
int u;
while(!q.empty()){
u = q.front();
q.pop();
for(int i = head[u]; i ; i =edge[i].nxt){
int v = edge[i].to;
int w = edge[i].c;
if(cval[u] > 0) cval[v] += w * cval[u];
if(vis[v]) continue;
vis[v] = 1;
q.push(v);
}
}
}
int main()
{
scanf("%d%d",&n,&p);
for(int i = 1; i <= n; ++ i){
scanf("%d%d",&cval[i],&uval[i]);
if(!cval[i]) cval[i] = -1 * uval[i];
}
for(int i = 1; i <= p; ++ i){
int x, y, z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
out[x] ++;
in[y] ++;
}
for(int i = 1; i <= n; ++ i){
if(!in[i]){
q.push(i);
vis[i] = 1;
}
}
bfs();
int flag = 0;
for(int i = 1; i <= n; ++ i){
if(!out[i] && cval[i] > 0){
flag = 1;
printf("%d %d
",i,cval[i]);
}
}
if(!flag) printf("NULL
");
return 0;
}
//
int n, m, T, p, top;
int head[N], cnt;
int cval[N], uval[N], in[N], out[N];
int q[N], h, t;
int vis[N];
struct node
{
int to;
int c;
int nxt;
}edge[N * 2];
inline void add(int u,int v,int w)
{
in[v] ++, out[u] ++;
edge[++cnt].to=v;
edge[cnt].c=w;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
void topu(){
int u;
h = 1;
while(h <= t){
u = q[h];
for(int i = head[u]; i; i = edge[i].nxt){
int v = edge[i].to;
if(vis[v]) continue;
vis[v] = 1;
q[++ t] = v;
}
h ++;
}
}
void solve(){
for(int i = t; i; -- i){
int u = q[i], sum = 0;
for(int j = head[u]; j; j = edge[j].nxt){
int v = edge[j].to;
int w = edge[j].c;
if(cval[v] > 0) sum += w * cval[v];
}
if(out[u]) cval[u] = sum - uval[u];
}
int flag = 0;
for(int i = 1; i <= n; ++ i){
if(!in[i] && cval[i] > 0){
flag = 1;
printf("%d %d
",i,cval[i]);
}
}
if(!flag) printf("NULL
");
}
int main()
{
scanf("%d%d",&n,&p);
for(int i = 1; i <= n; ++ i){
scanf("%d%d",&cval[i],&uval[i]);
}
for(int i = 1; i <= p; ++ i){
int x, y, z;
scanf("%d%d%d",&x,&y,&z);
add(y,x,z); //反向建图
}
for(int i = 1; i <= n; ++ i){
if(!in[i]) {
q[++ t] = i;
vis[i] = 1;
}
}
topu();
solve();
return 0;
}