题面
解法
拓扑排序:
看到这种有向图,而且图形结构类似于【HAOI2016】食物链,那么一般会想到利用拓扑排序
拓扑排序的大概过程应该都很清楚,这一题主要就是要怎么处理减去的 Ui ,因为第一层(即输入层)的 C 值是直接给定的,所以不需要减去U ,其他节点都需要减去 Ui ,因此我们可以给不是输入层的点打上标记,在进行拓扑排序时额外处理
最后要注意的就是输出输出层中大于零的项,负数项是不包括在内的
复杂度
O( m+n )
代码
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<queue>
#define Rint register int
#define Lint long long int
using namespace std;
const Lint M=998244353;
const int N=250;
struct node
{
int next,to,w;
}t[N*N];
int head[N],num;
int in[N],out[N];
Lint f[N],g[N],p[N];
int n,m;
queue<int> q;
void add(int u,int v,int w)
{
t[++num]=(node){ head[u],v,w };
head[u]=num;
}
void Top()
{
int tmp;
for(int i=1;i<=n;i++)
if( !in[i] && f[i] ) q.push( i ),p[i]=1;
while( !q.empty() )
{
tmp=q.front(),q.pop();
if( !p[tmp] ) f[tmp]=f[tmp]-g[tmp];
if( f[tmp]<=0 ) continue ;
for(int i=head[tmp],x; i ;i=t[i].next)
{
x=t[i].to;
in[x]--,f[x]+=t[i].w*f[tmp];
if( !in[x] ) q.push( x );
}
}
}
int main()
{
int u,v,w;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld%lld",&f[i],&g[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
out[u]++,in[v]++;
add( u,v,w );
}
Top();
u=0;
for(int i=1;i<=n;i++)
if( !out[i] && f[i]>0 )
printf("%d %lld\n",i,f[i]),u++;
if( !u ) printf("NULL\n");
return 0;
}