原题地址
https://www.luogu.org/problem/show?pid=1038
语死早、语体教系列……捋了好几遍都没看懂题干在说啥,试着写了写,一提交果然有bug……最后还是看着题解改了个bug才过,倍受打击……
广搜
解题思路
简单的广搜,用邻接表存图,入度为0的(或者c[i]>0的)点是输入层,先放到队列里,c[i]=0的不是输入层,要预处理一下,把c[i]换成c[i]-u[i](语死早语死早语死早……),然后中规中矩地跑bfs就好了,只要没入过队就可以入队,但只有本身c[i]>0才可以更新下面的点。注意bfs过程中搜到的点更新状态时不需要再-u[i],根据题意每个点只需要减一次,而前面我们已经预处理过了。输出层符合c[i]>0的编号放到一个数组里,广搜结束后进行排序(排的是编号),从小到大输出。
参考代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
intnum=0,v[105],b[105],c[105],u[105],ch[105],r[105];
bool vis[105];
queue<int>q;
struct mc
{
intx,y,l,ne;
}e[10005];
void put(int x,int y,int l)
{
num++;
e[num].x=x;
e[num].y=y;
e[num].l=l;
e[num].ne=v[x];
v[x]=num;
}
int main()
{
intn,p;
cin>>n>>p;
for(int i=1;i<=n;i++)
{
cin>>c[i]>>u[i];
if(!c[i]) c[i]-=u[i];
}
memset(r,0,sizeof(r));
memset(ch,0,sizeof(ch));
intx,y,z;
for(int i=1;i<=p;i++)
{
cin>>x>>y>>z;
put(x,y,z);
r[y]++;
ch[x]++;
}
for(int i=1;i<=n;i++)
if (!r[i]) q.push(i);
memset(vis,0,sizeof(vis));
intcnt=0;
while(!q.empty())
{
int x=q.front();
q.pop();
if (c[x]<=0) continue;
if (!ch[x]&&c[x]>0)
{
cnt++;
b[cnt]=x;
}
for (int i=v[x];i;i=e[i].ne)
{
int y=e[i].y;
c[y]+=e[i].l*c[x];
if(!vis[y])
{
q.push(y);
vis[y]=1;
}
}
}
if(cnt==0)
{
cout<<"NULL";
return0;
}
sort(b+1,b+cnt+1);
for(int i=1;i<=cnt;i++)
cout<<b[i]<<' '<<c[b[i]]<<endl;
return0;
}