3305. 作物杂交

题目链接

3305. 作物杂交

作物杂交是作物栽培中重要的一步。

已知有 \(N\) 种作物 (编号 \(1\)\(N\)),第 \(i\) 种作物从播种到成熟的时间为 \(T_i\)

作物之间两两可以进行杂交,杂交时间取两种中时间较长的一方。

如作物 \(A\) 种植时间为 \(5\) 天,作物 \(B\) 种植时间为 \(7\) 天,则 \(AB\) 杂交花费的时间为 \(7\) 天。

作物杂交会产生固定的作物,新产生的作物仍然属于 \(N\) 种作物中的一种。

初始时,拥有其中 \(M\) 种作物的种子 (数量无限,可以支持多次杂交)。

同时可以进行多个杂交过程。

求问对于给定的目标种子,最少需要多少天能够得到。

如存在 \(4\) 种作物 \(ABCD\),各自的成熟时间为 \(5\) 天、\(7\) 天、\(3\) 天、\(8\) 天。

初始拥有 \(AB\) 两种作物的种子,目标种子为 \(D\),已知杂交情况为 \(A×B→C\)\(A×C→D\)

则最短的杂交过程为:

\(1\) 天到第 \(7\) 天 (作物 \(B\) 的时间),\(A×B→C\)

\(8\) 天到第 \(12\) 天 (作物 \(A\) 的时间),\(A×C→D\)

花费 \(12\) 天得到作物 \(D\) 的种子。

输入格式

输入的第 \(1\) 行包含 \(4\) 个整数 \(N,M,K,T,N\) 表示作物种类总数 (编号 \(1\)\(N\)),\(M\) 表示初始拥有的作物种子类型数量,\(K\) 表示可以杂交的方案数,\(T\) 表示目标种子的编号。

\(2\) 行包含 \(N\) 个整数,其中第 \(i\) 个整数表示第 \(i\) 种作物的种植时间 \(T_i\)

\(3\) 行包含 \(M\) 个整数,分别表示已拥有的种子类型 \(K_j,K_j\) 两两不同。

\(4\)\(K+3\) 行,每行包含 \(3\) 个整数 \(A,B,C\),表示第 \(A\) 类作物和第 \(B\) 类作物杂交可以获得第 \(C\) 类作物的种子。

输出格式

输出一个整数,表示得到目标种子的最短杂交时间。

样例解释

\(1≤N≤2000,\)
\(2≤M≤N,\)
\(1≤K≤10^5,\)
\(1≤T≤N,\)
\(1≤T_i≤100,\)
\(1≤K_j≤M,\)
保证目标种子一定可以通过杂交得到。
不保证作物 \(A\)\(B\) 杂交只能生成作物 \(C\)(也就是说,\(A×B→C\)\(A×B→D\) 可能同时在输入中出现)
不保证作物 \(C\) 只能由作物 \(A\)\(B\) 杂交生成(也就是说,\(A×B→D\)\(A×C→D\) 可能同时在输入中出现)。
不保证同一杂交公式不在输入中重复出现。

输入样例:

6 2 4 6
5 3 4 6 4 9
1 2
1 2 3
1 3 4
2 3 5
4 5 6

输出样例:

16

样例解释

\(1\) 天至第 \(5\) 天,将编号 \(1\) 与编号 \(2\) 的作物杂交,得到编号 \(3\) 的作物种子。

\(6\) 天至第 \(10\) 天,将编号 \(1\) 与编号 \(3\) 的作物杂交,得到编号 \(4\) 的作物种子。

\(6\) 天至第 \(9\) 天,将编号 \(2\) 与编号 \(3\) 的作物杂交,得到编号 \(5\) 的作物种子。

\(11\) 天至第 \(16\) 天,将编号 \(4\) 与编号 \(5\) 的作物杂交,得到编号 \(6\) 的作物种子。

总共花费 \(16\) 天。

解题思路

dfs

反向考虑,求解目标的最短天数,先dfs求出合成目标的最短天数,这里需要注意合成一个种子在互不影响的前提下可以同时进行,这里记忆化搜索可以降低复杂度

  • 时间复杂度:\(O(m+n)\)

代码

// Problem: 作物杂交
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/3308/
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=2005,M=1e5+5,inf=0x3f3f3f3f;
vector<PII> adj[N];
int n,m,k,t,a[N],f[N],res=inf;
int dfs(int x)
{
	if(f[x]!=inf)return f[x];
	for(auto t:adj[x])
	{
		int y1=t.fi,y2=t.se;
		f[x]=min(f[x],max(dfs(y1),dfs(y2))+max(a[y1],a[y2]));
	}
	return f[x];
}
int main()
{
    cin>>n>>m>>k>>t;
    for(int i=1;i<=n;i++)cin>>a[i];
    memset(f,0x3f,sizeof f);
    for(int i=1;i<=m;i++)
    {
    	int s;
    	cin>>s;
    	f[s]=0;
    }
    for(int i=1;i<=k;i++)
    {
    	int y1,y2,x;
    	cin>>y1>>y2>>x;
    	adj[x].pb({y1,y2});
    }
    
    cout<<dfs(t);
    return 0;
}
posted @ 2022-04-06 23:17  zyy2001  阅读(172)  评论(0编辑  收藏  举报