[CC-SUBWAY]Subway Ride

题目大意:

一棵\(n(n\le5\times10^5)\)个点的含重边的树,总边数为\(m(m\le10^6)\),每条边有一个颜色。\(q(q\le5\times10^5)\)次询问,每次询问两个结点之间的路径(不经过重复结点)最多包含多少连续的同色段。

思路:

一个显然的结论是,对于连接相同两个点的重边,如果不同的颜色数量\(\le 3\),那么至少有一条边和路径两侧的颜色不相同,这时我们只需要发明一种新的颜色来代替这些颜色即可。因此每条边最多只需要保留\(2\)种颜色。

用\(f[i][0/1]\)表示到了第\(i\)个结点,上一条边是第\(0/1\)种颜色的答案。每次询问跑一遍这样的DP,单次的时间复杂度是\(\mathcal O(n)\)。

使用树上倍增的思想,\(f[i][j][k][l]\)表示\(i\sim anc[i][j]\)的路径上,第一条边是第\(k\)种颜色,最后一条边是第\(l\)种颜色,询问时将一整段转移即可。

时间复杂度\(\mathcal O(q\log n)\)。

源代码:

#include<map>
#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {register char ch;while(!isdigit(ch=getchar()));register int x=ch^'0';while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');return x;
}
const int N=5e5+1,logN=19;
int tot,anc[N][logN],dep[N],f[N][2],g[N][2];
int seg[N][logN][2][2],w[N][logN][2];
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {e[u].push_back(v);e[v].push_back(u);
}
std::map<std::pair<int,int>,std::pair<int,int>> map;
inline int lg2(const float &x) {return ((unsigned&)x>>23&255)-127;
}
inline void up(int &x,const int &y) {x=std::max(x,y);
}
void dfs(const int &x,const int &par) {if(par) {int u=x,v=par;if(u>v) std::swap(u,v);const auto &p=map[std::make_pair(u,v)];if(p.first) {w[x][0][0]=p.first;seg[x][0][0][0]=1;}if(p.second) {w[x][0][1]=p.second;seg[x][0][1][1]=1;}}anc[x][0]=par;dep[x]=dep[par]+1;for(register int i=1;i<=lg2(dep[x]);i++) {anc[x][i]=anc[anc[x][i-1]][i-1];w[x][i][0]=w[anc[x][i-1]][i-1][0];w[x][i][1]=w[anc[x][i-1]][i-1][1];for(register int j=0;j<2;j++) {if(!w[x][0][j]) continue;for(register int k=0;k<2;k++) {if(!w[x][i][k]) continue;for(register int l=0;l<2;l++) {if(!w[x][i-1][l]) continue;for(register int m=0;m<2;m++) {if(!w[anc[x][i-1]][0][m]) continue;up(seg[x][i][j][k],seg[x][i-1][j][l]+seg[anc[x][i-1]][i-1][m][k]-(w[x][i-1][l]==w[anc[x][i-1]][0][m]));}}}}}for(auto &y:e[x]) {if(y!=par) dfs(y,x);}
}
inline int query(int u,int v) {if(u==v) return 0;if(dep[u]<dep[v]) std::swap(u,v);f[u][0]=f[u][1]=g[u][0]=g[u][1]=0;f[v][0]=f[v][1]=g[v][0]=g[v][1]=0;for(register int i=lg2(dep[u]-dep[v]);i>=0;i--) {const int &p=anc[u][i];if(dep[p]<dep[v]) continue;f[p][0]=f[p][1]=g[p][0]=g[p][1]=0;for(register int j=0;j<2;j++) {for(register int k=0;k<2;k++) {if(!w[u][0][k]) continue;for(register int l=0;l<2;l++) {if(f[u][j]+seg[u][i][k][l]-(g[u][j]==w[u][0][k])>f[p][l]) {f[p][l]=f[u][j]+seg[u][i][k][l]-(g[u][j]==w[u][0][k]);g[p][l]=w[u][i][l];}}}}u=p;}if(u==v) return std::max(f[u][0],f[u][1])-1;for(register int i=lg2(dep[u]);i>=0;i--) {const int &p=anc[u][i],&q=anc[v][i];if(p==q) continue;f[p][0]=f[p][1]=g[p][0]=g[p][1]=0;for(register int j=0;j<2;j++) {for(register int k=0;k<2;k++) {if(!w[u][0][k]) continue;for(register int l=0;l<2;l++) {if(f[u][j]+seg[u][i][k][l]-(g[u][j]==w[u][0][k])>f[p][l]) {f[p][l]=f[u][j]+seg[u][i][k][l]-(g[u][j]==w[u][0][k]);g[p][l]=w[u][i][l];}}}}f[q][0]=f[q][1]=g[q][0]=g[q][1]=0;for(register int j=0;j<2;j++) {for(register int k=0;k<2;k++) {if(!w[v][0][k]) continue;for(register int l=0;l<2;l++) {if(f[v][j]+seg[v][i][k][l]-(g[v][j]==w[v][0][k])>f[q][l]) {f[q][l]=f[v][j]+seg[v][i][k][l]-(g[v][j]==w[v][0][k]);g[q][l]=w[v][i][l];}}}}u=p;v=q;}int p=anc[u][0];f[p][0]=f[p][1]=g[p][0]=g[p][1]=0;for(register int j=0;j<2;j++) {for(register int k=0;k<2;k++) {if(!w[u][0][k]) continue;if(f[u][j]+seg[u][0][k][k]-(g[u][j]==w[u][0][k])>f[p][k]) {f[p][k]=f[u][j]+seg[u][0][k][k]-(g[u][j]==w[u][0][k]);g[p][k]=w[u][0][k];}}}p=0;f[p][0]=f[p][1]=g[p][0]=g[p][1]=0;for(register int j=0;j<2;j++) {for(register int k=0;k<2;k++) {if(!w[v][0][k]) continue;if(f[v][j]+seg[v][0][k][k]-(g[v][j]==w[v][0][k])>f[p][k]) {f[p][k]=f[v][j]+seg[v][0][k][k]-(g[v][j]==w[v][0][k]);g[p][k]=w[v][0][k];}}}int ans=0;for(register int i=0;i<2;i++) {for(register int j=0;j<2;j++) {up(ans,f[anc[u][0]][i]+f[0][j]-(g[anc[u][0]][i]==g[0][j]));}}return ans-1;
}
int main() {const int n=getint(),m=getint();for(register int i=0;i<m;i++) {int u=getint(),v=getint(),c=getint();if(u>v) std::swap(u,v);auto &p=map[std::make_pair(u,v)];if(p.first<0) continue;if(p.first==c||p.second==c) continue;if(p.first==0) {add_edge(u,v);p.first=c;continue;}if(p.second==0) {p.second=c;continue;}p.first=--tot;p.second=0;}dfs(1,0);const int q=getint();for(register int i=0;i<q;i++) {printf("%d\n",query(getint(),getint()));}return 0;
}

转载于:https://www.cnblogs.com/skylee03/p/9512101.html

[CC-SUBWAY]Subway Ride相关推荐

  1. 双向广搜的DIJKSTRA算法--简易的北京地铁导航实现

    本学期的课程设计,实现最短路的算法,于是采用了DIJKSTRA算法,并用双向广搜优化了. 实现了简易的北京地铁导航.于是把代码分享出来. (核心代码是find_min(),Dijkstra()部分) ...

  2. 石家庄地铁线路查询系统

    石家庄地铁线路查询系统开发: 合作人:张旺 数据库的设计为:建立了一张表,有line_id(路线号).stop_id(站号).stop_name(站名).change(某站可换乘的线号)这几列. st ...

  3. 结对开发石家庄地铁系统

    我和袁鹏一组,代码如下 util层的代码是: package util;import java.sql.Connection; import java.sql.DriverManager; impor ...

  4. Android开发中常见的设计模式

    对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...

  5. 视频异常检测 综述(一)

    视频异常检测 综述(一) 文章目录 视频异常检测 综述(一) 一.视频异常检测(Video anomaly detection)的定义 二.单场景&多场景 三.视频异常类型 1.Appeara ...

  6. 简单的爬取某租房网站租房信息并存入MySQL数据库

    这是我第一个爬虫项目,因为我有一些其他语言的基础,所以在入坑python十来天后终于完成了一个小项目,其间的辛酸不足为外人道也...说了这么多,那就让我们开始吧. 1.先看看使用的库: import ...

  7. Python爬取链家网上的房源信息

    import re # 正则表达式,进行文字匹配 from bs4 import BeautifulSoup # 网页解析,获取数据 import urllib.request, urllib.err ...

  8. python实现北京租房信息计算

    案例说明 在本次案例中,我们将通过 Python 爬虫技术获取某网数万条北京租房数据,用北京部分城区真实房价分析真实的房租情况:数据获取.数据清洗预览.数据分析可视化,一起了解最近房租的状况. 本次实 ...

  9. 课程设计:基于Python的爬虫租房数据分析

    1.课程设计 1.1.设计目的: 通过项目设计,全面掌握数据采集和预处理的原理和应用范围,掌握数据采集的过程,完成数据清洗,存储和展示,熟悉运用数据采集和预处理的相关工具 1.2.开发背景: 现实情况 ...

  10. Python爬虫爬取链家网上的房源信息练习

    一 原链接:用Python爬虫爬取链家网上的房源信息_shayebuhui_a的博客-CSDN博客_python爬取链家 打开链家网页:https://sh.lianjia.com/zufang/  ...

最新文章

  1. 今日头条反爬措施形同虚设,论多平台协同在安全方面的重要性
  2. 【廖雪峰python入门笔记】函数
  3. 用Photoshop打造怀旧色调美女照片
  4. 第7课第2节_Binder系统_c++实现_编译测试
  5. linux杀sqlplus进程,sqlplus / as sysdba 在linux系统所发起进程
  6. mongodb修改数据语句_mongodb之一些简单的增删改查语句
  7. php-v 查看不到版本,解決php -v查看到版本於phpinfo()打印的版本不一致問題
  8. ijkplayer 消息循环处理过程分析
  9. string类的基本实现
  10. bzoj 4393 Usaco Fruit Feast
  11. 嵌入式Linux系统编程学习之二十四消息队列
  12. 如何获取ezui tree 所有子节点
  13. 语言输出奇树有多少总方法_新手如何快速学习一门编程语言?了解 TA,三周学好C语言...
  14. 大学计算机社团学什么好,大学哪些社团组织最值得加入?很多人工作后才知道!...
  15. 听哥一句劝,CSDN史上最强插件你把握不住(文末可抽取机械键盘,CSDN年卡会员)
  16. 计算机维护费可以跨年吗,税控技术维护费跨年可以抵扣吗_增值税
  17. linux终端删除文件命令_如何在Linux终端中删除文件和目录
  18. HTML网页设计基础期末作业——绿色化妆品网页(HTML+CSS)
  19. mysql中$和_在数据库中,$和#代表什么意思?
  20. 云师大商学院计算机,高考倒计时,云师大商学院为考生加油!

热门文章

  1. matlab百分位数图,Fanchart-可视化时间序列数据的百分位数【含Matlab源码】
  2. AI时代的三类人:探索掌握AIGC,引领未来的人才之路
  3. 择一城终老,携一人白首
  4. Unity菜单树模糊查询
  5. 虚幻4模型提取_【UnrealEngine4】从虚幻四的着色模型到NPR
  6. 浅谈药企如何选择药品流向系统
  7. tauri简单教程——以Flash应用为例
  8. python项目--物流行业项目分析
  9. 麻辣烫与安卓主线程工作原理
  10. 为什么程序员都反感笔试?