首页 > 其他分享 >注视一切的终结

注视一切的终结

时间:2023-10-18 22:46:14浏览次数:28  
标签:cnt fu int 终结 fa lca 注视 col 一切

注视一切的终结

目录

题目大意

给出一个 \(n\) 个点 \(m\) 条边的图,每条边有一个颜色 \(w_i\) 。保证这个图删除了所有重边后变成一棵树

一条路径的权值就是相邻的两条边的 \(w_i\) 值不相同的个数

有 \(Q\) 次询问,每次询问给出两个点 \(x , y\) ,求 \(x\) 到 \(y\) 的所有简单路径的权值的最大值

简单路径:路径上的所有顶点不重复。

思路

倍增、 \(dp\)

显然,对于两个点之间的边,我们只用维护至多 \(3\) 种不同颜色的就可以了

设 \(dp_{x , i , a , b}\) 表示一条 \(x\) 到距离它的 \(2^i\) 距离的祖先的一条路径,靠近 \(x\) 的那一端的颜色是 \(a\) ,\(x\) 的 \(2 ^ i\) 级祖先上面的那条边是 \(b\) 的路径的最大权值。

那么

\[f_{x , 0 , a , b} = (col_a \neq col_b) \]

转移是枚举 \(x,y = fa_{x , i - 1} , z = fa_{x , i}\) ,颜色分别设为 \(a , b , c\) ,则转移为 \(f_{x , i , a , b} = \max\{f_{x , i - 1 , a , b} + f_{y , i - 1 , b , c}\}\)

对于每个询问 \(x , y\)

设他们的 \(lca\) 的儿子节点分别是 \(fx , fy\) ,分别求出 \(cx_i , cy_j\) 表示 \(fx , fy\) 到 \(lca\) 的所有不同颜色的边的最大权值。

若其中一个点是 \(lca\) ,那么答案就是另一个点的最大值,否则再枚举一遍 \(lca\) 下两条边的颜色 \(ans = \max\{cx_a +cy_b + (col_a \neq col_b)\}\)

代码超级难调

code

#include <bits/stdc++.h>
#define fu(x , y , z) for(int x = y ; x <= z ; x ++)
#define fd(x , y , z) for(int x = y ; x >= z ; x --)
using namespace std;
const int N = 5e5 + 5 , M = 1e6 + 5;
int ecnt , hd[N] , fa[N][21] , dep[N] , vis[N] , cnt[N] , col[N][4] , f[N][21][4][4] , n , m;
struct E {
    int to , nt , w;
} e[M << 1];
void add (int x , int y , int z) { e[++ecnt].to = y , e[ecnt].w = z , e[ecnt].nt = hd[x] , hd[x] = ecnt; }
int Lca (int x , int y) {
    if (dep[x] < dep[y]) swap (x , y);
    fd (i , 20 , 0) 
        if (dep[fa[x][i]] >= dep[y])
            x = fa[x][i];
    if (x == y) 
        return x;
    fd (i , 20 , 0) 
        if (fa[x][i] != fa[y][i])
            x = fa[x][i] , y = fa[y][i];
    return fa[x][0];
}
void dfs1 (int x) {
    vis[x] = 1;
    fu (i , 1 , 20) 
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    int y;
    for (int i = hd[x] ; i ; i = e[i].nt) {
        y = e[i].to;
        if (y == fa[x][0]) {
            if (cnt[x] == 3) continue;
            int flg = 0;
            fu (j , 1 , cnt[x]) 
                if (col[x][j] == e[i].w) {
                    flg = 1;
                    break;
                }
            if (flg) continue;
            col[x][++cnt[x]] = e[i].w;
        }
        if (vis[y]) continue;
        dep[y] = dep[x] + 1;
        fa[y][0] = x;
        dfs1 (y);
    }
}
void dfs2 (int x) {
    vis[x] = 1;
    int y;
    if (x != 1) {
        y = fa[x][0];
        fu (j , 1 , cnt[x]) 
            fu (k , 1 , cnt[fa[x][0]])
                f[x][0][j][k] = (col[x][j] != col[fa[x][0]][k]); 
    }
    int z;
    for(int i=1;(1<<i)<=dep[x];i++) {
        y = fa[x][i - 1] , z = fa[x][i];
        fu (a , 1 , cnt[x]) {
            fu (b , 1 , cnt[y]) {
                fu (c , 1 , cnt[z]) {
                    f[x][i][a][c] = max (f[x][i][a][c] , f[x][i - 1][a][b] + f[y][i - 1][b][c]);
                }
            }
        }
    }
    for (int i = hd[x] ; i ; i = e[i].nt) {
        y = e[i].to;
        if (vis[y]) continue;
        dfs2 (y);
    }
}
int jump (int x , int d , int c[]) {
    int cc[5] , y;
    fd (i , 20 , 0) {
        if (dep[fa[x][i]] > d) {
            y = fa[x][i];
            memset (cc , 0 , sizeof (cc));
            fu (a , 1 , cnt[x])
                fu (b , 1 , cnt[y])
                    cc[b] = max (cc[b] , c[a] + f[x][i][a][b]);
            x = fa[x][i];
            memcpy (c , cc , sizeof (cc));
        }
    }
    return x;
}
int main () { 
    // freopen ("a.in" , "r" , stdin);
    // freopen ("c.out" , "w" , stdout);
    int u , v , w;
    scanf ("%d%d" , &n , &m);
    fu (i , 1 , m) {
        scanf ("%d%d%d" , &u , &v , &w);
        add (u , v , w) , add (v , u , w);
    }
    dep[1] = 1;
    dfs1 (1);
    fu (i , 1 , n) vis[i] = 0;
    dfs2 (1);
    int T , x , y , lca , fx , fy , cx[5] , cy[5] , ans;
    scanf ("%d" , &T);
    int ans1 =  0;
    while (T --) {
        memset (cx , 0 , sizeof (cx)) , memset (cy , 0 , sizeof (cy));
        fx = fy = 0;
        scanf ("%d%d" , &x , &y);
        lca = Lca (x , y);
        if (x != lca) fx = jump (x , dep[lca] , cx);
        if (y != lca) fy = jump (y , dep[lca] , cy);
        ans = 0;
        if (x == lca)
            fu (i , 1 , cnt[fy]) 
                ans = max (ans , cy[i]);
        else if (y == lca) 
            fu (i , 1 , cnt[fx])
                ans = max (ans , cx[i]);
        else {
            fu (i , 1 , cnt[fx]) {
                fu (j , 1 , cnt[fy]) {
                    ans = max (ans , cx[i] + cy[j] + (col[fx][i] != col[fy][j]));
                }
            }
        } 
        printf ("%d\n" , ans);
    }
    return 0;
}

标签:cnt,fu,int,终结,fa,lca,注视,col,一切
From: https://www.cnblogs.com/2020fengziyang/p/17773559.html

相关文章

  • Intel官方确认:“X代酷睿”终结!不再有15代
    Intel刚刚正式发布了代号RaptorLakeRefresh的第14代酷睿处理器,12月14日还会发布代号MeteorLake的全新第一代酷睿Ultra处理器。对于Intel这一次的品牌变化,很多玩家一直比较迷茫,毕竟目前正处于过渡阶段。在最新的QA解读中,Intel确认,RaptorLakeRefresh将是最后一代使用“X代酷......
  • LCD时代即将终结!曝苹果新iPad升级为OLED屏
    市场调研机构Omdia在一份报告中提到,苹果将在2024年推出配备OLED屏的iPadPro,有11和13英寸两种尺寸,供应商为三星和LG。报告指出,苹果目标是2024年生产1000万台OLED版iPadPro,其中三星供货400万台,LG供货600万台。展望未来,苹果还将会在iPadmini和iPadAir产品线上使用OLED,届时苹果......
  • 芝诺悖论之“阿基里斯与乌龟”的终结性思考
    “阿基里斯与乌龟”是公元前五世纪古希腊芝诺提出的悖论,想必大家都已耳熟能详了。乌龟只要还在阿基里斯前头,那么阿基里斯是一直处于追的状态,换句话说在这种状态下他一直没追上。哪怕乌龟的领先优势越来越小,直至很小,非常小,阿基里斯还是没追上。但是,这个小,不是无限的小的,它的物理尺度......
  • AspNetCore不明确的匹配异常-请求与多个终结点匹配
    框架:net6.0AspNetCoreMVC添加区域控制器HomeController,直接启动报错;因默认路由下存在相同的控制器HomeController(非区域的),需要修改路由映射配置;在Program.cs添加区域路由配置app.MapAreaControllerRoute(name:"areaRoute",areaName:"Admin",pattern:......
  • 在一切开始之前,在过去结束之后
    在一切开始之前,在过去结束之后目录在一切开始之前,在过去结束之后在过去结束之后在一切开始之前解决过去留下的问题散功、重修什么是散功重修重修什么结语日期:2023.09.14在开始写下第一行之前我很困,昨晚睡的实在不好,又有一点失眠。至于为什么失眠,不重要。在过去结束之后首先......
  • 第一部分 1.1 信息与信息技术 1.1.1信息与数据 信息的概念: 一般认为:信息是在自然界
    第一部分1.1信息与信息技术1.1.1信息与数据信息的概念: 一般认为:信息是在自然界、人类社会和人类思维活动中普遍存在的一切物质和事物的属性。 信息能够用来消除事物不确定的因素数据的概念: 是指存储在某种媒体上可以加以鉴别的符号资料。(符号,不仅指文字、字母和数字等,还包括......
  • 《线性代数》1. 一切从向量开始
    什么是向量我们在初等数学的时候,研究的都是一个数,而到线性代数,我们将从研究一个数拓展到研究一组数,而一组数的基本表示方法就是向量(Vector)。向量是线性代数研究的基本元素,它就是一组数,比如\((1,2,3)\)就是一个向量。那么问题来了,向量究竟有什么作用呢?或者说我们研究一组数有......
  • 对未来真正的慷慨,是把一切献给现在
    高级工程师掌握CS基础知识。他们不一定了解高难度的数据结构和算法,也可能无法证明一些理论的正确性,但他们对最常用的知识有自己深刻的理解。他们可以轻松实现基本数据结构,并且能快速判断用哪种实现方式相对更好。这在大部分工作场景中是能降低人力和后期维护、开发成本的。......
  • 关于Azure-存储账户-文件共享的内网访问-专用终结点连接-配置说明
    这里以标准性能的StorageV2的存储账户为例(即同时包含了容器,文件共享,队列,表)本文的实验环境,是想让Azure上的虚拟机通过内网访问文件共享,而数据连接不走Internet公网我们可以使用到存储账户,菜单下的Networking配置,下面的【专用终结点连接|Privateendpointconnections】 创建......
  • 学习 ChatGPT 一切基础知识的绝佳资源
    推荐:使用NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景OpenAI,ChatGPT,GPT系列和大型语言模型(LLM)一般-如果你与人工智能专业或技术专家有远程联系,你很有可能会在几乎所有的商业对话中听到这些词这些天。炒作是真实的。我们不能再称它为泡沫了。毕竟,这一次,炒作正在兑现其承......