[CC-SUBWAY]Subway Ride
[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相关推荐
- 双向广搜的DIJKSTRA算法--简易的北京地铁导航实现
本学期的课程设计,实现最短路的算法,于是采用了DIJKSTRA算法,并用双向广搜优化了. 实现了简易的北京地铁导航.于是把代码分享出来. (核心代码是find_min(),Dijkstra()部分) ...
- 石家庄地铁线路查询系统
石家庄地铁线路查询系统开发: 合作人:张旺 数据库的设计为:建立了一张表,有line_id(路线号).stop_id(站号).stop_name(站名).change(某站可换乘的线号)这几列. st ...
- 结对开发石家庄地铁系统
我和袁鹏一组,代码如下 util层的代码是: package util;import java.sql.Connection; import java.sql.DriverManager; impor ...
- Android开发中常见的设计模式
对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...
- 视频异常检测 综述(一)
视频异常检测 综述(一) 文章目录 视频异常检测 综述(一) 一.视频异常检测(Video anomaly detection)的定义 二.单场景&多场景 三.视频异常类型 1.Appeara ...
- 简单的爬取某租房网站租房信息并存入MySQL数据库
这是我第一个爬虫项目,因为我有一些其他语言的基础,所以在入坑python十来天后终于完成了一个小项目,其间的辛酸不足为外人道也...说了这么多,那就让我们开始吧. 1.先看看使用的库: import ...
- Python爬取链家网上的房源信息
import re # 正则表达式,进行文字匹配 from bs4 import BeautifulSoup # 网页解析,获取数据 import urllib.request, urllib.err ...
- python实现北京租房信息计算
案例说明 在本次案例中,我们将通过 Python 爬虫技术获取某网数万条北京租房数据,用北京部分城区真实房价分析真实的房租情况:数据获取.数据清洗预览.数据分析可视化,一起了解最近房租的状况. 本次实 ...
- 课程设计:基于Python的爬虫租房数据分析
1.课程设计 1.1.设计目的: 通过项目设计,全面掌握数据采集和预处理的原理和应用范围,掌握数据采集的过程,完成数据清洗,存储和展示,熟悉运用数据采集和预处理的相关工具 1.2.开发背景: 现实情况 ...
- Python爬虫爬取链家网上的房源信息练习
一 原链接:用Python爬虫爬取链家网上的房源信息_shayebuhui_a的博客-CSDN博客_python爬取链家 打开链家网页:https://sh.lianjia.com/zufang/ ...
最新文章
- 今日头条反爬措施形同虚设,论多平台协同在安全方面的重要性
- 【廖雪峰python入门笔记】函数
- 用Photoshop打造怀旧色调美女照片
- 第7课第2节_Binder系统_c++实现_编译测试
- linux杀sqlplus进程,sqlplus / as sysdba 在linux系统所发起进程
- mongodb修改数据语句_mongodb之一些简单的增删改查语句
- php-v 查看不到版本,解決php -v查看到版本於phpinfo()打印的版本不一致問題
- ijkplayer 消息循环处理过程分析
- string类的基本实现
- bzoj 4393 Usaco Fruit Feast
- 嵌入式Linux系统编程学习之二十四消息队列
- 如何获取ezui tree 所有子节点
- 语言输出奇树有多少总方法_新手如何快速学习一门编程语言?了解 TA,三周学好C语言...
- 大学计算机社团学什么好,大学哪些社团组织最值得加入?很多人工作后才知道!...
- 听哥一句劝,CSDN史上最强插件你把握不住(文末可抽取机械键盘,CSDN年卡会员)
- 计算机维护费可以跨年吗,税控技术维护费跨年可以抵扣吗_增值税
- linux终端删除文件命令_如何在Linux终端中删除文件和目录
- HTML网页设计基础期末作业——绿色化妆品网页(HTML+CSS)
- mysql中$和_在数据库中,$和#代表什么意思?
- 云师大商学院计算机,高考倒计时,云师大商学院为考生加油!