读优没读负数调了0.5h+,日
大概就是跑一下拓扑排序再算每个 C 就行了
注意输入层的节点不用减去其阈值
#include <iostream>
#include <cstdio>
#include <queue>
const int MaxN = 200 + 5;
int N, M, Edge, Topn;
int Indegree[MaxN], Outdegree[MaxN], FST[MaxN], U[MaxN], C[MaxN], Top[MaxN];
bool IsNull;
std::queue <int> Q;
struct Linker
{
int to, w, nxt;
Linker(){}
Linker(int x, int y, int z)
{
to = y;
w = z;
nxt = FST[x];
}
} E[MaxN * MaxN];
inline int read()
{
register int x = 0, v = 1;
register char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') v = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * v;
}
inline void AddEdge(int x, int y, int z)
{
E[++Edge] = Linker(x, y, z);
FST[x] = Edge;
}
int main()
{
N = read();
M = read();
for(int i = 1; i <= N; ++i)
{
C[i] = read();
U[i] = read();
if(!C[i]) C[i] -= U[i];
}
for(int i = 1; i <= M; ++i)
{
int u = read(), v = read(), w = read();
AddEdge(u, v, w);
++Indegree[v];
++Outdegree[u];
}
for(int i = 1; i <= N; ++i)
{
if(!Indegree[i])
{
Q.push(i);
Top[++Topn] = i;
}
}
while(!Q.empty())
{
int from = Q.front();
Q.pop();
for(int k = FST[from]; k; k = E[k].nxt)
{
int to = E[k].to;
if(--Indegree[to] == 0)
{
Q.push(to);
Top[++Topn] = to;
}
}
}
for(int i = 1; i <= N; ++i)
{
int cur = Top[i];
if(C[cur] <= 0) continue;
for(int k = FST[cur]; k; k = E[k].nxt)
{
int to = E[k].to, w = E[k].w;
C[to] += w * C[cur];
}
}
for(int i = 1; i <= N; ++i)
{
if(!Outdegree[i] && C[i] > 0)
{
IsNull = 1;
printf("%d %d\n", i, C[i]);
}
}
if(!IsNull)
{
puts("NULL");
return 0;
}
return 0;
}