2023-03-28 18:41阅读: 28评论: 0推荐: 0

作物杂交

原文
版权归属: GabrielxD
本文链接: https://gabrielxd.top/archives/acwing-3305
许可协议: 本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权

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

思路 动态规划 SPFA算法

本题是用 Bellman-Ford 的本质——动态规划来思考,而因为 SPFA 算法是 Bellman-Ford 算法的宽搜优化,所以可以用 SPFA 算法进行优化。
image

状态转移方程:f(i,j)=min(f(i,j),max(f(i1,x),f(i1,y))+max(Tx,Ty))
按照该状态表示, f(n1,t) 就是答案(得到目标种子的最短杂交时间),因为从初始种子迭代到目标种子最多只会经过 n1 条边。

时间复杂度:O(NK) ,按照本题的数据范围是 O(2×108) ,显然会超时,但是加一个小优化就可以过 :如果在某一次迭代中 没有任何作物的最小花费时间被更新 ,那就说明已经找到了最优解。

另外也可以使用 SPFA 算法进行优化,首先因为状态都是从上一层转移过来的,所以动归中第一维的 i 可以直接被优化掉,其次观察状态转移方程发现:每次只有在 f(x) 或者 f(y) 发生变化后 f(j) 才有可能被更新,所以可以直接利用 SPFA算法进行宽搜优化。

SPFA代码

SPFA的思想是 通过进行两边建边将两个前提作物改为一个为前驱节点、一个为边的权值,进而可以建图。

#include <bits/stdc++.h>
using namespace std;
const int N=2020,M=2e5+10;
int n,m,k,t;
int T[N],K[N];
int h[N],to[M],w[M],pre[M],idx;
void add(int a,int b,int c){
to[idx]=c,w[idx]=b,pre[idx]=h[a],h[a]=idx++;
}
int dist[N];
int vis[N],st[N];
void SPFA(){
memset(dist,0x3f , sizeof dist);
queue<int> q;
for(int i=1;i<=m;i++){
q.push(K[i]),st[K[i]]=1,dist[K[i]]=0;
}
while(q.size()){
int a=q.front();
q.pop();st[a]=0;
for(int i=h[a];i!=-1;i=pre[i]){
int c=to[i],b=w[i];
int dis= max(dist[a],dist[b])+ max(T[b],T[a]);
if(dist[c]>dis){
dist[c]=dis; // 如果原材料有更新 产物就有机会被更新
if(!st[c])
q.push(c),st[c]=1;
}
}
}
}
int main(){
memset(h,-1,sizeof h);
cin>>n>>m>>k>>t;
for(int i=1;i<=n;i++){
int o;cin>>o;T[i]=o;
}
for(int i=1;i<=m;i++){
int o;cin>>o;K[i]=o;
}
for(int i=1;i<=k;i++){
int a, b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
SPFA();
cout<<dist[t]<<endl;
return 0;
}

本文作者:kingwzun

本文链接:https://www.cnblogs.com/kingwz/p/17266327.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   kingwzun  阅读(28)  评论(0编辑  收藏  举报
历史上的今天:
2022-03-28 MySQL学习
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起