Luogu8268 solution

Problem

link->https://www.luogu.com.cn/problem/P8268

Solution

在我看来,这是一道递归好题。

我们来考虑怎样查询 \(x\) 金属是否能够生产(或者已经有 \(x\) 金属):

  • 如果本身就有 \(x\) 金属,将 \(x\) 金属个数 \(-1\),返回 true

  • 如果本身没有 \(x\) 金属且没有 \(x\) 金属的生产配方,返回 false

  • 如果本身没有 \(x\) 金属且有 \(x\) 金属的生产配方,则询问生产配方里的每个金属是否能够生产(或者已经有该金属),若均能生产,则返回 true,反之返回 false

由于 \(x\) 金属的配方 \(\le 1\) 个且能制造 \(x\) 金属的金属的编号全部 \(< x\),则,我们可以将制造 \(n\) 金属的生产过程构成一棵树。

当然,其中有一点点小小的问题:如果没有 \(x\) 金属但有 \(x\) 金属的生产配方,则我们之前对 \(x\) 生产配方里的每个金属也进行了询问,其中极有可能会有能够生产的,则那些能够生产的金属的数量不是减去了一点吗?但是那些金属最终并没有被用于生产 \(x\) 金属上,则那些金属不是被浪费了吗?

事实上,不需要担心此类事情的发生,因为在生产 \(x\) 金属的过程中,一旦有其中一个金属无法生产,则 \(x\) 金属也无法生产,递归也就没法继续进行,所以我们不需要担心那些被浪费的金属。

Code

#include<bits/stdc++.h>
#define pd push_back
#define pb pop_back
#define mk make_pair
//#define int long long
#define PII pair<int,int>
#define _for(a,b,c) for(int a=b;a<=c;a++)
#define _rep(a,b,c) for(int a=b;a>=c;a--)
using namespace std;
template <typename T> inline void read(T& x) {
	x=0; T 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&15); ch=getchar(); }
	x=x*f;
	return;
}
template <typename T,typename ...Arg> inline void read(T& x,Arg& ...arg){
	read(x); read(arg...);
}
int power(int a,int b) {
	int ans=1;
	do {
		if(b&1) ans*=a; a*=a;
	} while(b>>=1);
	return ans;
}
const int N=105;
int a[N],n,k;
vector<int> v[N];
bool Solve(int x) {
    if(a[x]) return a[x]--; //本身就有 x 金属(这里运用了非 0 值在 bool 中 =1 的特性)
	if(v[x].empty()&&!a[x]) return 0; //没有 x 金属且没有生产 x 金属的配方
	_for(i,0,v[x].size()-1) //没有 x 金属,但有 x 金属的配方
		if(!Solve(v[x][i]))
		    return 0;
	return 1;
}
signed main() {
	read(n);
	_for(i,1,n)
		read(a[i]);
	read(k);
	while(k--) {
		int l,m;
		read(l,m);
		while(m--) { //l 金属的配方
			int x; read(x); v[l].pd(x);
		}
	}
	int ans=0;
	while(Solve(n)) //当能生产 x 金属时一直生产
		ans++;
	printf("%d",ans);
	return 1;
}

接下来我们来谈一谈一下为什么不能直接查询能生产的 \(x\) 金属的个数而是查询能否生产 \(x\) 金属。

题目并没有规定一个金属只能出现在一个金属的生产配方中。

举个栗子,我们假定生产 \(x\) 金属需要 \(x_1\)\(x_2\) 金属,而生产 \(x_1\) 金属需要 \(x_3\)\(x_4\) 金属,生产 \(x_2\) 需要 \(x_3\)\(x_5\) 金属。

可以发现,生产 \(x_1\)\(x_2\) 金属均需要使用 \(x_3\) 金属,如果我们将 \(x_3\) 全部用于生产 \(x_1\) 金属上,则 \(x_2\) 金属就无法生产,而没有 \(x_2\) 金属就无法生产 \(x\) 金属。

Hack:

6
4 4 4 0 0 0
3
6 2 4 5
5 2 1 2
4 2 1 3

时间复杂度应为 \(\Theta(\sum a_i)\)

posted @ 2022-08-01 12:15  lsj2009  阅读(29)  评论(0)    收藏  举报