传送门

首先(想了很久之后)注意到一个性质:同一条边有多种颜色的话保留3种就可以了,这是因为假如最优解要求当前位置与相邻两条边都不相同,那么只要有3条边,就肯定可以满足这一点。

完事就做一个nlogn*3^4的倍增dp就行了……实际肯定是跑不满的(而且cc机子快)。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 510000
using namespace std; int n,m,l[MN],F[MN][],_F[MN][],v[MN][][][],num=,x,y,w,C[MN][],de[MN];
struct na{
int y,w,ne;
}b[MN<<];
inline void add(int x,int y,int w){b[++num].y=y;b[num].w=w;b[num].ne=l[x];l[x]=num;}
void dfs(int x,int f){
if (F[x][]) return;
F[x][]=x;F[x][]=f;
for (int i=;i<;i++)
if (!(F[x][i]=F[F[F[x][i-]][i-]][])) break;
_F[x][]=f;
for (int i=;i<;i++)
if (!(_F[x][i]=_F[_F[x][i-]][i-])) break; for (int i=l[x];i;i=b[i].ne)
if (b[i].y!=f){
dfs(b[i].y,x);
if (!C[b[i].y][]) C[b[i].y][]=b[i].w;else
if (!C[b[i].y][]) C[b[i].y][]=b[i].w;else
if (!C[b[i].y][]) C[b[i].y][]=b[i].w;
}
}
void DFS(int x,int f){
if (de[x]) return;
de[x]=de[f]+; for (int a=;a<;a++)
for (int b=;b<;b++)
if (a!=b) v[x][][a][b]=-1e8; int tmp1,tmp2,tmp3;
for (int i=;i<;i++)
if (_F[x][i])
for (int a=;a<;a++)
if (C[x][a])
for (int b=;b<;b++)
if (C[F[x][i]][b])
for (int A=;A<;A++)
if (C[F[x][i-]][A])
if ((tmp1=v[x][i-][a][A])>=)
for (int B=;B<;B++)
if (C[_F[x][i-]][B])
if ((tmp2=v[_F[x][i-]][i-][B][b])>=)
if (v[x][i][a][b]<(tmp3=tmp1+tmp2+(C[F[x][i-]][A]!=C[_F[x][i-]][B]))) v[x][i][a][b]=tmp3; for (int i=l[x];i;i=b[i].ne)
if (b[i].y!=x) DFS(b[i].y,x);
}
inline int ask(int x,int y){
if (de[x]>de[y]) swap(x,y);
int ans[][],la[];
memset(ans,,sizeof(ans));
memset(la,,sizeof(la));
for (int i=;i>=;i--)
if (de[_F[y][i]]>=de[x]){
if (la[]==){
for (int a=;a<;a++)
for (int b=;b<;b++)
if (ans[][b]<v[y][i][a][b])
ans[][b]=v[y][i][a][b];
la[]=F[y][i];
y=_F[y][i];
}else{
int tmp[]={,,},TMP;
for (int a=;a<;a++)
if (C[la[]][a])
for (int b=;b<;b++)
if (C[y][b])
for (int c=;c<;c++)
if (C[F[y][i]][c])
if (tmp[c]<(TMP=ans[][a]+v[y][i][b][c]+(C[la[]][a]!=C[y][b]))) tmp[c]=TMP;
for (int a=;a<;a++) ans[][a]=tmp[a]; la[]=F[y][i];
y=_F[y][i];
}
}
if (x==y){
int tmp=;
for (int a=;a<;a++) if (ans[][a]>tmp) tmp=ans[][a];
return tmp;
}
int st[]={x,y};
for (int i=;i>=;i--)
if (_F[st[]][i]!=_F[st[]][i]){
for (int j=;j<;j++){
if (la[j]==){
for (int a=;a<;a++)
for (int b=;b<;b++)
if (ans[j][b]<v[st[j]][i][a][b])
ans[j][b]=v[st[j]][i][a][b];
la[j]=F[st[j]][i];
st[j]=_F[st[j]][i];
}else{
int tmp[]={-,-,-},TMP;
for (int a=;a<;a++)
if (C[la[j]][a])
for (int b=;b<;b++)
if (C[st[j]][b])
for (int c=;c<;c++)
if (C[F[st[j]][i]][c])
if (tmp[c]<(TMP=ans[j][a]+v[st[j]][i][b][c]+(C[la[j]][a]!=C[st[j]][b]))) tmp[c]=TMP;
for (int a=;a<;a++) ans[j][a]=tmp[a]; la[j]=F[st[j]][i];
st[j]=_F[st[j]][i];
}
}
}
int i=;
for (int j=;j<;j++){
if (la[j]==){
for (int a=;a<;a++)
for (int b=;b<;b++)
if (ans[j][b]<v[st[j]][i][a][b])
ans[j][b]=v[st[j]][i][a][b];
la[j]=F[st[j]][i];
st[j]=_F[st[j]][i];
}else{
int tmp[]={-,-,-},TMP;
for (int a=;a<;a++)
if (C[la[j]][a])
for (int b=;b<;b++)
if (C[st[j]][b])
for (int c=;c<;c++)
if (C[F[st[j]][i]][c])
if (tmp[c]<(TMP=ans[j][a]+v[st[j]][i][b][c]+(C[la[j]][a]!=C[st[j]][b]))) tmp[c]=TMP;
for (int a=;a<;a++) ans[j][a]=tmp[a]; la[j]=F[st[j]][i];
st[j]=_F[st[j]][i];
}
}
int tmp=;
for (int a=;a<;a++)
for (int b=;b<;b++)
if (tmp<ans[][a]+ans[][b]+(C[la[]][a]!=C[la[]][b])) tmp=ans[][a]+ans[][b]+(C[la[]][a]!=C[la[]][b]);
return tmp;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=;i<=m;i++){
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);add(y,x,w);
}
dfs(,);DFS(,);
//printf(">_<%d %d %d\n",C[3][0],C[3][1],C[3][2]);
/*for (int i=1;i<=n;i++,puts("")){
printf("%d:",i);
for (int j=0;j<3;j++) printf("%d ",C[i][j]);
}*/
//printf("%d %d\n",v[6][2][0][0],_F[6][2]);
scanf("%d",&m);
while(m--){
scanf("%d%d",&x,&y);
printf("%d\n",ask(x,y));
}
}

Codechef July Challenge 2018 : Subway Ride的更多相关文章

  1. Codechef July Challenge 2018 : Picking Fruit for Chefs

    传送门 好久没写题解了,就过来水两篇. 对于每一个人,考虑一个序列$A$,$A_I$表示当k取值为 i 时的答案. 如果说有两个人,我们可以把$(A+B)^k$二项式展开,这样就发现把两个人合并起来的 ...

  2. Codechef October Challenge 2018 游记

    Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...

  3. Codechef September Challenge 2018 游记

    Codechef September Challenge 2018 游记 Magician versus Chef 题目大意: 有一排\(n(n\le10^5)\)个格子,一开始硬币在第\(x\)个格 ...

  4. codechef February Challenge 2018 简要题解

    比赛链接:https://www.codechef.com/FEB18,题面和提交记录是公开的,这里就不再贴了 Chef And His Characters 模拟题 Chef And The Pat ...

  5. Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal

    原文链接http://www.cnblogs.com/zhouzhendong/p/9010945.html 题目传送门 - Codechef STMINCUT 题意 在一个有边权的无向图中,我们定义 ...

  6. Codechef August Challenge 2018 : Chef at the River

    传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...

  7. Codechef August Challenge 2018 : Safe Partition

    传送门 (虽然是A了但是不知道复杂度是不是正确的 考虑以某个位置为结尾的合法划分 先考虑min,带来的影响是限制了最小长度,预处理出这个最小长度后,这可以在处理到这个数时,把不能算的部分去掉(不满足m ...

  8. Codechef August Challenge 2018 : Interactive Matrix

    传送门 首先整个矩阵可以被分为很多小矩阵,小矩阵内所有行的单调性是一样的,所有列的单调性是一样的. 考虑如何在这样一个小矩阵中找出答案.我的策略是每次取四个角中最大值和最小值的点,这样可以每次删掉一行 ...

  9. Codechef August Challenge 2018 : Lonely Cycles

    传送门 几波树形dp就行了. #include<cstdio> #include<cstring> #include<algorithm> #define MN 5 ...

随机推荐

  1. 解决Java getResource 路径中含有中文的情况

    问题描述 当Java调用getResource方法,但是因为路径中含有中文时,得不到正确的路径 问题分析 编码转换问题 当我们使用ClassLoader的getResource方法获取路径时,获取到的 ...

  2. [物理学与PDEs]第1章习题11 各向同性导体中电荷分布的指数衰减

    在各向同性的导体中, Ohm 定律具有如下形式: $$\bex {\bf j}=\sigma {\bf E}, \eex$$ 其中 $\sigma$ 称为电导率. 试证在真空中导体的连续性方程为 $$ ...

  3. [物理学与PDEs]第1章第9节 Darwin 模型 9.2 Maxwell 方程组的一个定解问题

    设 $\Omega$ 为一有界区域, 外部为理想导体 $(\sigma=+\infty)$, 则 $\Omega$ 中电磁场满足 Maxwell 方程组 $$\beex \bea \ve\cfrac{ ...

  4. centos7安装notepadqq

    这是在centos7 上发表的第一篇博文 对linux系统陌生,折腾了一天,安装好了搜狗输入法.相关文章也不少,但照着一步一步来,都没有成功.最后照着这篇弄成了: ****** 安装notepadd+ ...

  5. 第29月第14天 evpp

    1.evpp https://github.com/Qihoo360/evpp/tree/master/examples/recipes/self_control_timer https://blog ...

  6. openwrt 加入nand flash的支持

    参考链接 :   https://blog.csdn.net/wwx0715/article/details/77189456?locationNum=9&fps=1

  7. Oracle 自定义函数、存储过程

    讲函数之前,先介绍一下程序结构 3.程序结构 新建一个测试窗口,举一个小例子 declare -- 声明变量,包括游标 begin -- 执行部分 dbms_output.put_line('hell ...

  8. 爬虫工程师JD归纳

    核心能力归纳 负责:多平台信息的抓取,清洗和分析工作 要求: 熟悉常用开源爬虫框架,如 scrapy / pyspider
 了解基于Cookie的登录原理,熟悉常用的信息抽取技术,如正则表达式.XP ...

  9. codeblocks添加编译选项

    -std=c++0x

  10. 【原创】大数据基础之Spark(5)Shuffle实现原理及代码解析

    一 简介 Shuffle,简而言之,就是对数据进行重新分区,其中会涉及大量的网络io和磁盘io,为什么需要shuffle,以词频统计reduceByKey过程为例, serverA:partition ...