题目描述:
作物杂交是作物栽培中重要的一步。已知有 NN 种作物 (编号 11 至 NN ),第 ii 种作物从播种到成熟的时间为 T_iTi。作物之间两两可以进行杂交,杂交时间取两种中时间较长的一方。如作物 A 种植时间为 5 天,作物 B 种植时间为 7 天,则 AB 杂交花费的时间为 7 天。作物杂交会产生固定的作物,新产生的作物仍然属于 NN 种作物中的一种。
初始时,拥有其中 MM 种作物的种子 (数量无限,可以支持多次杂交)。同时可以进行多个杂交过程。求问对于给定的目标种子,最少需要多少天能够得到。
如存在 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, TN,M,K,T,NN 表示作物种类总数 (编号 11 至 NN),MM 表示初始拥有的作物种子类型数量,KK 表示可以杂交的方案数,TT 表示目标种子的编号。
第 2 行包含 NN 个整数,其中第 ii 个整数表示第 ii 种作物的种植时间 T_i\ (1 \leq T_i \leq 100)Ti (1≤Ti≤100)。
第 3 行包含 MM 个整数,分别表示已拥有的种子类型 K_j\ (1 \leq K_j \leq M)Kj (1≤Kj≤M),K_jKj 两两不同。
第 4 至 KK + 3 行,每行包含 3 个整数 A, B,CA,B,C,表示第 AA 类作物和第 BB 类作物杂交可以获得第 CC 类作物的种子。
其中, N1≤N≤2000,2≤M≤N,1≤K≤105,1≤T≤N, 保证目标种子一定可以通过杂交得到。
输出描述:
输出一个整数,表示得到目标种子的最短杂交时间。
样例:
6 2 4 6
5 3 4 6 4 9
1 2
1 2 3
1 3 4
2 3 5
4 5 6
解决方案:
该题的难点在于如何根据题目的输入进行建图。这里采用以杂交植物作为目标节点的建图方法建立有向图。
采用邻接链表的表示方法,其中将顶点定义为杂交方案组成的结构体。代码如下:
#include
#include
#include
#include
using namespace std;
const int N = 100010;
const int INF = 0x3f3f3f3f;
int h[N],ne[N],idx; //邻接链表
int n,m,k,t;
int Time[N]; //表示每种作物的生长时间
int color[N]; //标记是否已出现
int g[N]; //表示总杂交时间
//邻接表中存储的应是作物的杂交方案
struct E{
int a,b;
}e[N];
void add(int a,int b,int c){
e[idx].a=b;e[idx].b=c;
ne[idx] = h[a];
h[a] = idx++;
} //邻接表的插入操作
int dfs(int u){
if(color[u]) return g[u]; //目标结点已经被访问过说明已计算过时间,直接返回
for(int i=h[u];i!=-1;i=ne[i]){
E j=e[i];
g[u] = min(g[u],max(Time[j.a],Time[j.b])+max(dfs(j.a),dfs(j.b)));//递归计算杂交时间,两种作物的生长时间最大值和杂交时间最大值
}
color[u]=true;//标记被访问
return g[u];
}
int main()
{
// 请在此输入您的代码
ios::sync_with_stdio(false);
memset(h,-1,sizeof h); //初始化邻接表
memset(g,INF,sizeof g); //将初始杂交时间设为无穷大
cin>>n>>m>>k>>t;
for(int i=1;i<=n;i++){
cin>>Time[i];
} //输入时间
for(int i=0;i>temp;
color[temp]=1;
g[temp]=0; //已有作物杂交时间为0
}
for(int i=1;i<=k;i++){
int a,b,c;
cin>>a>>b>>c;
add(c,a,b);
} //建立邻接表
dfs(t);
cout<