传送门
这题水的一堪……大概就是给你一个点的被激活的限制条件,然后给你点的有向边的连接,问你最后有多少出度为0的点的状态不是0
直接拓扑排序就行了,当这个点的入度为0且满足激发条件就激发他,然后接着往下做……
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#define N 200+5
#define M 40000+5
using namespace std;
struct graph
{
int next,to,val;
graph () {}
graph (int _next,int _to,int _val)
:next(_next),to(_to),val(_val){}
}edge[M];
int head[N];
inline long long read()
{
long long x=0,f=1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')f=-1;ch = getchar();}
while(ch >='0' && ch <='9'){x=(x<<1)+(x<<3)+ch-'0';ch = getchar();}
return x*f;
}
inline void add(int x,int y,int z)
{
static int cnt = 0;
edge[++cnt] = graph(head[x],y,z);
head[x]=cnt;
}
struct point
{
int in;
int c;
int u;
bool first;
bool last;
}a[N];
queue <int> Q;
int main()
{
int n,p;
cin>>n>>p;
for(int i=1;i<=n;++i)a[i].c=read(),a[i].u=read();
for(int i=1;i<=p;++i)
{
int x=read(),y=read(),z=read();
a[y].in++ ;
a[y].first = true;
a[x].last = true;
add(x,y,z);
}
for(int i=1;i<=n;++i)
if(!a[i].first)
Q.push(i);
while(!Q.empty())
{
int tt=Q.front();
Q.pop();
for(int i=head[tt];i;i=edge[i].next)
{
int t = edge[i].to;
a[t].in--;
a[t].c += edge[i].val * a[tt].c;
if(! a[t].in && a[t].c-a[t].u > 0)
{
a[t].c -= a[t].u;
Q.push(t);
}
}
}
bool flag = false;
for(int i=1;i<=n;++i)
{
if(!a[i].last && a[i].c>0)
{
flag = true;
printf("%d %d\n",i,a[i].c);
}
}
if(!flag)
puts("NULL");
}