首页 > 其他分享 >AcWing 3305. 作物杂交 (spfa建边变形版本

AcWing 3305. 作物杂交 (spfa建边变形版本

时间:2023-11-26 14:44:05浏览次数:35  
标签:dist int spfa static 建边 sc new AcWing

package 蓝桥杯;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class lanqiao1443 {
    static final int N = 2010, M = 2 * 100010;
    static int[] h, e, ne, w, target;
    static int[] dist;
    static int n, m, k, t;
    static int idx;
    static boolean[] st;
    static Queue<Integer> q;

    /**
     * 思路 : 另类的spfa建图方式 (spfa的本质是动态规划)
     *       本题不寻常于普通的图论主要是因为普通图论是一个点到另一个点, 但是这个图是一个点借助别的点到另一个点
     *       所以需要从本质出发, 重新推导一下spfa的公式
     *       先说一下最重要的存边方式, 我们的h[i]发生了改变, 此处的h[i]所串起来的邻接表表示i这个点可以和后面邻接表上的点杂交产生对应的target
     *       我们用一个例子讲解一下边权的存储 :
     *       比如我x + y => z
     *       那么我h[x]中必定有个点是y, 其对应的target就是z
     *       那么我从x + y -> z (或者从y + z -> z) 的边权 w 就是 max(w[x], w[y])
     *       那我我就需要看看dist[z] 的答案是否需要更新成 max(dist[x], dist[y]) + max(w[x], w[y]) 这个东西
     *
     *       总结下来存的信息其实是两个 a --(w, b)--> c  b --(w, a)--> c 其中w = max(w[x], w[y])
     *
     *       看明白了以后其实就是套spfa的板子了, 可以看看基础课的板子怎么写的
     * */

    private static void init() {
        h = new int[N]; // 邻接表
        e = new int[M];
        ne = new int[M];
        target = new int[M];
        w = new int[N]; // 每个作物成熟的花费时间
        dist = new int[N]; // dist数组
        st = new boolean[N]; // spfa用的是否在队列中数组
        q = new LinkedList<>(); // 队列
        Arrays.fill(dist, 0x3f3f3f3f); // 初始化
        Arrays.fill(h, -1); // 初始化
    }

    private static void add(int a, int b, int c) {
        e[idx] = b; target[idx] = c; ne[idx] = h[a]; h[a] = idx ++ ;
    }

    private static void spfa() {
        while (!q.isEmpty()) {
            int x = q.poll();
            st[x] = false;

            for (int i = h[x]; i != -1; i = ne[i]) {
                int y = e[i], z = target[i];

                if (dist[z] > Math.max(dist[x], dist[y]) + Math.max(w[x], w[y])) {
                    dist[z] = Math.max(dist[x], dist[y]) + Math.max(w[x], w[y]);
                    q.add(z);
                    if (!st[z]) {
                        q.add(z);
                        st[z] = true;
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt(); m = sc.nextInt(); k = sc.nextInt(); t = sc.nextInt();
        init();
        for (int i = 1; i <= n; i ++ ) w[i] = sc.nextInt();


        while (m -- > 0) { // 将所有拥有的种子的dist更新成0, 并且入队
            int x = sc.nextInt();
            dist[x] = 0;
            q.add(x);
            st[x] = true;
        }

        while (k -- > 0) {
            int a = sc.nextInt(), b = sc.nextInt(), c = sc.nextInt();
            add(a, b, c); // 加边, a配合b合成c
            add(b, a, c); // 加边, b配合a合成c
        }

        spfa();

        System.out.println(dist[t]);
    }
}

标签:dist,int,spfa,static,建边,sc,new,AcWing
From: https://www.cnblogs.com/llihaotian666/p/17857195.html

相关文章

  • AcWing 903. 昂贵的聘礼 (超级源点 + 等级限制 + 抽象建图
    package算法提高课;importjava.util.Arrays;importjava.util.Scanner;publicclassacw903{staticintm,n;staticint[]dis,level;staticboolean[]st;staticint[][]g;/**思路:首先用到了虚拟源点,加入了等级限制*......
  • 对acwing193的解释
    首先是估价函数的解释由于\(x\)较大,所以\(x\)一直平方是最快的能到达\(p\)及以上的方法,所以这个估价函数比实际代价小(或等)再看\(gcd\)这个剪枝把八种情况列出,如果\(x\)和\(y\)都是\(gcd=d\)的倍数,那么加减或翻倍之后的新的\(x\)和\(y\)一定也是\(d\)的倍数,所以可以剪枝......
  • acwing 第 130 场周赛  (前缀和,dfs,对不同边的处理)
      #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<climits>usingnamespacestd;typedeflonglongLL;constintN=5010;intn;inta[N];LLs[N];LLget(intl,intr){return......
  • AcWing 算法基础课week 1 总结(万字长文)
    AcWing算法基础课week1总结总结点1:快速排序(分治思想)题1:从小到大排序主体思路:定义一个数x属于数组s,利用双指针,将数组分为大于等于x和小于等于x的两部分,然后递归处理。(具体步骤如下)1.如上图所示,我们定义一个数组s用来储存n个数据,然后定义两个指针ij,分别指向数组的左右两......
  • Acwing.第130场周赛
    Acwing.第130场周赛比赛链接A.最大数和最小数题目链接思路:简单模拟,使用max()和min()函数就可以了代码:#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ inta,b,c; cin>>a>>b>>c; cout<<max(a,max(b,c))<<""<<min(a,min(b,c))<......
  • AcWing 1017. 怪盗基德的滑翔翼——最长上升子序列
    最长上升子序列1、\(O(n^{2})\)简单DP做法\[dp[i]=\max_{h[j]<h[i]}[dp[j]+1]\]#include<bits/stdc++.h>usingnamespacestd;constintN=105;inth[N];intdp[N];intmain(){intT;cin>>T;while(T--){intn;cin>......
  • acwing276机器任务的证明
    假设我们已经给每一个任务分配了一种模式了那么相同模式的任务排在一起的时候肯定重启次数最小对涉及到的模式,我们还原回二分图上就是在二分图上尽量选择少的节点(一种模式代表一次重启次数,因为相同模式都是放在一起的),使每一个任务都可以被安排就可以转换为最小点覆盖问题......
  • acwing374导弹防御塔分析
    二分是怎么想到的?我们假设已经找到了最终的方案,那么每一座防御塔都被分到了一些敌人去攻击那么这个方案的时间是多少呢?就是每个防御塔的时间的最大值每个防御塔的时间是他所分配的这些敌人里面所需要花费最长的时间去攻击的敌人的时间相当于最大值最小,所以想到二分acwing上的......
  • ACwing 334 K匿名序列
    首先这道题很容易发现如果已经知道了最后的答案序列,那么操作顺序是无所谓的所以我们可以假设从头操作到尾由于题目给的是非严格递增序列,我们猜想最后的答案一定是一段一段的,段与段之间单调递增比如1112222233455反证:如果最终的答案序列存在\(a_{i}\)和\(a_{j}\),其......
  • Acwing.第 129 场周赛
    Acwing.第129场周赛比赛地址A.字符串题目思路:只需要用到reverse()反转函数就可以代码:#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ strings; cin>>s; reverse(s.begin(),s.end()); cout<<s<<endl; }intmain(){ intt=1; while(t--){ solv......