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)\)。

浙公网安备 33010602011771号