作物杂交
原文
版权归属: GabrielxD
本文链接: https://gabrielxd.top/archives/acwing-3305
许可协议: 本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
输出描述
输出一个整数,表示得到目标种子的最短杂交时间。
思路 动态规划 SPFA算法
本题是用 Bellman-Ford 的本质——动态规划来思考,而因为 SPFA 算法是 Bellman-Ford 算法的宽搜优化,所以可以用 SPFA 算法进行优化。
状态转移方程:
按照该状态表示, 就是答案(得到目标种子的最短杂交时间),因为从初始种子迭代到目标种子最多只会经过 条边。
时间复杂度: ,按照本题的数据范围是 ,显然会超时,但是加一个小优化就可以过 :如果在某一次迭代中 没有任何作物的最小花费时间被更新 ,那就说明已经找到了最优解。
另外也可以使用 SPFA 算法进行优化,首先因为状态都是从上一层转移过来的,所以动归中第一维的 可以直接被优化掉,其次观察状态转移方程发现:每次只有在 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 中国大陆许可协议进行许可。
分类:
标签:
,
,
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-03-28 MySQL学习