WC2018 通道

好久以前开的坑.
到今天才填上.

首先考虑队第一颗树边分,然后分成两个集合\(L,R\),在第二棵树上建出虚树,在每个路径\(lca\)处统计答案,维护点集的直径只有正权很好维护.

#include <bits/stdc++.h>using namespace std;
typedef long long ll;
typedef pair<int,int> p;
typedef pair<p,p> pp;
struct edge{int x;ll w;bool operator ==(const edge &_) const{return x==_.x&&w==_.w;}void print(){cerr<<"{"<<x<<","<<w<<"} ";}
};
typedef vector<edge> vi;
typedef vector<vector<edge> > vvi;
vi operator +(const vi &a,const vi &b){vi ret(a);ret.insert(ret.end(),b.begin(),b.end());return ret;
}
ostream& operator <<(ostream &ou,const p &a){return ou<<"["<<a.first<<","<<a.second<<"]";
}
const int N=100010;
int n;
namespace Tree3{vvi TG;int dep[N],top[N],fa[N],sz[N],son[N];ll dis[N];int getlca(int x,int y){while (top[x]!=top[y]){if (dep[top[x]]>dep[top[y]]) swap(x,y);y=fa[top[y]];}return dep[x]<dep[y]?x:y;}ll getdis(int x,int y){return dis[x]+dis[y]-2*dis[getlca(x,y)];}void Dfs(int x,int f=0){fa[x]=f;dep[x]=dep[f]+1;sz[x]=1;for (auto i:TG[x])if (i.x!=f){dis[i.x]=dis[x]+i.w;Dfs(i.x,x);sz[x]+=sz[i.x];if (sz[i.x]>sz[son[x]]) son[x]=i.x;}}void Sfd(int x,int tp,int f=0){top[x]=tp;if (son[x]) Sfd(son[x],tp,x);for (auto i:TG[x])if (i.x!=f&&i.x!=son[x]) Sfd(i.x,i.x,x);}void read(){TG.resize(n+1);for (int i=1; i<n; ++i){int x,y;ll w;scanf("%d%d%lld",&x,&y,&w);TG[x].push_back({y,w});TG[y].push_back({x,w});}Dfs(1);Sfd(1,1);}
}
namespace Tree2{const ll INF=1e18;vvi TG;int dep[N],col[N],clk,dfn[N],fa[N][17],dtime;ll dis[N],cost[N],ret;pp diameter[N];vector<int> E[N];int getlca(int x,int y){if (dep[x]>dep[y]) swap(x,y);for (int i=16; i>=0; --i) if (dep[fa[y][i]]>=dep[x]) y=fa[y][i];if (x==y) return x;for (int i=16; i>=0; --i) if (fa[y][i]!=fa[x][i]) x=fa[x][i],y=fa[y][i];return fa[x][0];}void Dfs(int x,int f=0){fa[x][0]=f;for (int i=1; i<17; ++i) fa[x][i]=fa[fa[x][i-1]][i-1];dfn[x]=++clk;dep[x]=dep[f]+1;for (auto i:TG[x])if (i.x!=f){dis[i.x]=dis[x]+i.w;Dfs(i.x,x);}}void read(){//cerr<<"readbegin2"<<endl;TG.resize(n+1);for (int i=1; i<n; ++i){int u,v;ll w;scanf("%d%d%lld",&u,&v,&w);TG[u].push_back({v,w});TG[v].push_back({u,w});}Dfs(1);//cerr<<"readend2"<<endl;}bool cmp(const edge &a,const edge &b){return dfn[a.x]<dfn[b.x];}ll calc(int a,int b){if (!(a&&b)) return (a||b)?-INF:-2*INF;if (a==b) return 0;//cerr<<"calc"<<a<<" "<<b<<" "<<cost[a]+cost[b]+dis[a]+dis[b]+Tree3::getdis(a,b)<<" "<<dis[a]+dis[b]<<endl;return cost[a]+cost[b]+dis[a]+dis[b]+Tree3::getdis(a,b);}ll calc(const p &a,const p &b){return max(max(calc(a.first,b.second),calc(a.first,b.first)),max(calc(a.second,b.first),calc(a.second,b.second)));}p operator +(const p &a,int b){ll t=calc(a.first,a.second);ll t2=calc(a.first,b);ll t3=calc(a.second,b);return max(t2,t3)>t?p({t2>=t3?a.first:a.second,b}):a;}p operator +(const p &a,const p &b){return (a+b.first)+b.second;}pp operator +(const pp &a,const pp &b){return {a.first+b.first,a.second+b.second};}p tr(int x){return {x,x};}int tim,vis[N],faf[N];void dfs(int x){//cerr<<"dfs on virtual tree:"<<x<<" "<<dis[x]<<endl;diameter[x]={tr(col[x]&1?x:0),tr(col[x]&1?0:x)};//cerr<<diameter[x].first<<" "<<diameter[x].second<<" "<<ret<<endl;for (auto i:E[x]){dfs(i);ret=max(ret,calc(diameter[x].first,diameter[i].second)-dis[x]*2);ret=max(ret,calc(diameter[x].second,diameter[i].first)-dis[x]*2);//cerr<<"aftmerge"<<x<<" "<<i<<" "<<diameter[x].first<<" "<<diameter[x].second<<" "<<ret<<" "<<dis[x]<<endl;diameter[x]=diameter[x]+diameter[i];}faf[x]=0;E[x].clear();//cerr<<"endi"<<x<<" "<<diameter[x].first<<" "<<diameter[x].second<<" "<<ret<<endl;}ll build_virtual_tree(vi a){sort(a.begin(),a.end(),cmp);stack<int> s;int rt=a[0].x;ret=0;vector<int> vim;for (auto i:a){vim.push_back(i.x);if (s.size()){int lca=getlca(s.top(),i.x);vim.push_back(lca);//cerr<<"build"<<i.x<<" "<<lca<<" "<<faf[1]<<endl;if (dep[lca]<dep[rt]) rt=lca;while (dep[faf[s.top()]]>dep[lca]) s.pop();bool cd=(faf[s.top()]!=lca);if (cd) faf[lca]=faf[s.top()];if (s.top()!=lca) faf[s.top()]=lca;s.pop();if (cd) s.push(lca);faf[i.x]=lca;}s.push(i.x);}++tim;for (auto i:vim)if (vis[i]<tim){vis[i]=tim;//cerr<<"fa"<<i<<" "<<faf[i]<<endl;E[faf[i]].push_back(i);}//cerr<<"ESZE"<<E[rt].size()<<" "<<rt<<endl;//exit(0);dfs(rt);return ret;}ll main(vi &u,vi &v){if (!(u.size()&&v.size())) return -INF;++dtime;for (auto i:u){col[i.x]=dtime;cost[i.x]=i.w;}++dtime;for (auto i:v){col[i.x]=dtime;cost[i.x]=i.w;}return build_virtual_tree(u+v);}
}
namespace Tree1{vvi G,TG;int sz[N<<1];int aa,bb,cnt,val;ll ans,ww;void dfs(int x,int f){for (auto i:TG[x])if (i.x!=f) dfs(i.x,x);int now=x;for (auto i:TG[x])if (i.x!=f){G[now].push_back({i.x,i.w});G[i.x].push_back({now,i.w});//cerr<<"cdr"<<now<<" "<<i.x<<" "<<i.w<<endl;++cnt;G[now].push_back({cnt,0});G[cnt].push_back({now,0});//cerr<<"car"<<now<<" "<<cnt<<" "<<0<<endl;now=cnt;}}void getsz(int x,int f=0){sz[x]=1;for (auto i:G[x])if (i.x!=f){getsz(i.x,x);sz[x]+=sz[i.x];}}void dfs(int x,int f,ll len){if (max(val-sz[x],sz[x])<max(val-sz[aa],sz[aa])){aa=x;bb=f;ww=len;}for (auto i:G[x])if (i.x!=f) dfs(i.x,x,i.w);}void Getpoint(int x,vi &g,int f=0,ll dis=0){if (x<=n) g.push_back({x,dis});for (auto i:G[x]) if (i.x!=f) Getpoint(i.x,g,x,dis+i.w);}void BF(int x){//cerr<<"BF"<<x<<endl;getsz(x);//cerr<<"getend"<<endl;aa=x;bb=0;val=sz[x];if (val==1) return;//cerr<<"dfsbegin"<<endl;dfs(x,0,0);//cerr<<"dfsend"<<aa<<" "<<bb<<" "<<ww<<" "<<(find(G[aa].begin(),G[aa].end(),edge{bb,ww})==G[aa].end())<<endl;G[aa].erase(find(G[aa].begin(),G[aa].end(),edge{bb,ww}));G[bb].erase(find(G[bb].begin(),G[bb].end(),edge{aa,ww}));//cerr<<"???"<<endl;vi u,v;Getpoint(aa,u);Getpoint(bb,v);//cerr<<"U:"<<endl;//for (auto i:u) i.print();//cerr<<endl<<"V:"<<endl;//for (auto i:v) i.print();//cerr<<endl<<"What's the edge:"<<aa<<" "<<bb<<" "<<ww<<endl;ans=max(ans,Tree2::main(u,v)+ww);//cerr<<"inthisans:"<<ans<<endl;//exit(0);int tmp=bb;BF(aa);BF(tmp);}void main(){scanf("%d",&n);TG.resize(n+1);G.resize(2*n);cnt=n;for (int i=1; i<n; ++i){int u,v;ll w;scanf("%d%d%lld",&u,&v,&w);TG[u].push_back({v,w});TG[v].push_back({u,w});}Tree2::read();Tree3::read();/*for (int i=1; i<=n; ++i)for (int j=1; j<=n; ++j)cerr<<i<<" "<<j<<" "<<Tree3::getdis(i,j)<<endl;*/dfs(1,0);BF(1);cout<<ans;}
}
int main(){Tree1::main();
}

转载于:https://www.cnblogs.com/Yuhuger/p/10575258.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javaScript第一天(1)

01-JavaScript基础 核心知识点 javaScript书写位置javaScript变量javaScript数据类型javaScript数据类型转换javaScript运算符 今日学习目标 能够定义一个变量并完成变量的赋值能够说出每一种具体的数据类型能够数据类型之间的相互转化能够掌握各种运算符的作用 序言 Java…

javaScript第二天(1)

02-JavaScript基础 1.核心知识点 运算符分支语句 【重点】断点调试 [查看程序逻辑的一个技能] 2.今日学习目标 能够掌握js中相关的运算符 能够掌握理解算数运算符使用及特点能够掌握赋值运算符的使用及特点能够掌握一元运算符的使用及特点能够掌握比较运算符的特点,理解等于…

第四周总结

第四周作业 这次作业属于哪个课程C语言程序设计这个作业要求在哪里第四周作业我的课程目标全部学会这个作业在那个具体方面帮助我实现目标深入了解二维数组参考文献教科书一&#xff0c;基础作业 程序填空题5-1 输入一个正整数 n (1≤n≤10)和n 阶方阵a的元素&#xff0c;如果方…

2019春季学期第四周作业

2019春季学期第四周作业 这个作业属于那个课程C语言程序设计Ⅰ这次作业要求在哪里2019春季学期第四周作业我在这个课程的目标是我希望能够更加掌握循环和排序参考文献无选择法排序 本题要求将给定的n个整数从大到小排序后输出。输入格式&#xff1a; 输入第一行给出一个不超过1…

javaScript第二天(2)

02JavaScript基础随堂笔记 01.运算符[☆] 知识点-算数运算符 作用就是进行 加, 减, 乘, 除 , 取余运算的 算数运算符的重点是通过算数运算和可以实现类型转换 加号可以实现数据类型转换: 一个数字和一个空字串相加最后的结果就是字符串减号也可以实现数据类型转换乘法符号也可…

MFC中的基本知识

转载于:https://www.cnblogs.com/o8le/archive/2012/05/21/2512178.html

Python中字符串操作函数string.split('str1')和string.join(ls)

Python中的字符串操作函数split 和 join能够实现字符串和列表之间的简单转换&#xff0c; 使用 .split()可以将字符串中特定部分以多个字符的形式&#xff0c;存储成列表 1 def split(self, *args, **kwargs): # real signature unknown2 """3 …

javaScript第三天(1)

03-JavaScript基础 1.核心知识点 分支语句 【重点】断点调试 [查看程序逻辑的一个技能]循环语句[重点 ☆☆☆] 2.今日学习目标 能够掌握条件判断分支语句能够掌握switch分支语句能够掌握三元表达式分支语句能够掌握循环语句 条件判断&#xff08;分支&#xff09; 语法 //…

关于单链表的头插法和尾插法

#include<stdio.h>#include<stdlib.h> typedef struct Node { // 定义的链表类型 int data; struct Node *next; }LNode , *Linklist; void print(Linklist L){ //这是一个将链表数据输出的函数 Linklist temL; whi…

javascript第三天(2)

03JavaScript基础课堂笔记 01-分支语句 知识点-多条件判断分支语句 语法 if(条件) {代码1 }else if(条件) {代码2 }else if(条件) {代码3 }else {代码4 }执行过程 1. 代码自上而下执行 2. 程序先判断第一个条件是否成立 true 还是 false 3. 如何第一个条件的结果是 true,那么就…

男生英文名大全

起个好听的英文名很重要吆&#xff01;既要好记&#xff0c;好听又要富有寓意。。。 AARON (希伯来)启发的意思&#xff0c;AARON被描绘为不高但英俊的男人&#xff0c;诚实刻苦具有责任感&#xff0c;是个有效率个性沉靜的领导者。 ABEL (希伯来)"呼吸"的意思&am…

Codeforces Round #548 (Div. 2) A. Even Substrings

You are given a string ??1?2…??ss1s2…sn of length ?n, which only contains digits 11, 22, ..., 99. A substring ?[?…?]s[l…r] of ?s is a string ????1??2…??slsl1sl2…sr. A substring ?[?…?]s[l…r] of ?s is called even if the number r…

VI编辑器常用命令

vi —终端中的编辑器 vi 简介 打开和新建文件 三种工作模式 常用命令 分屏命令 01. vi 简介 1.1 学习 vi 的目的 在工作中&#xff0c;要对 服务器 上的文件进行 简单 的修改&#xff0c;可以使用 ssh 远程登录到服务器上&#xff0c;并且使用 vi 进行快速的编辑即可 常见…

kubectl 常用命令

1. 查看镜像定义的内容 docker image inspeck 镜像名:版本 2. 查看可回滚历史 # myapp-deploy 指定哪个 deployment kubectl rollout history deployment myapp-deploy 3. 回滚到上一个版本 # rollout undo 回滚到上一版本的 deployment kubectl rollout undo deployment mya…

javaScript基础讲义第四天(1)

05-javaScript基础 核心知识点 数组操作字符串方式获取系统时间Math相关方法 今日目标 能够完成数组相关案例能后获取系统时间能够操作随机数能够完成小娜案例**[最终的目标]** 数组 思考如果我们希望同时保存多条数据该怎么办&#xff1f;【例如&#xff1a;如何将班上所…

20175213 2018-2019-2 《Java程序设计》第4周学习总结

## 教材学习内容总结 在第四周的学习过程中&#xff0c;我学习了第五章的内容。 第五章内容总结&#xff1a; 1.子类继承的方法只能操作子类继承和隐藏的成员变量。 2.子类和父类在同一包的继承性 子类自然继承了其父类中不是private的成员作为自己的成员。 3.子类和父类不在同…

Machine Schedule为什么UVA过了POJ过不了

UVA1194 POJ1325 POJ要多判一个非零&#xff01;&#xff01;&#xff01; #include<cstdio> #include<vector> #include<cstring> using namespace std; vector<int>e[105]; int vis[105]; int link[105]; int t; int find(int x) {for(int i0;i<e…

课堂笔记

javaScript基础 01.数组 复习数组 数组的意义 程序中可能会遇到一次保存多条数据情况,使用数组解决问题.数组也是一个保存数据的一个容器定义 通过字面量方式定义数组(推荐) var ary [];通过构造函数定义数组(了解) var ary new Array();赋值 通过索引的方式给数组赋值 va…

写一个使两个整数进行交换的方法(不能使用临时变量) 【前端每日一题-27】...

写一个使两个整数进行交换的方法&#xff08;不能使用临时变量&#xff09;这道题是一个比较有意思的题&#xff0c;记录于此。var a10; var b20;...不用临时变量让a和b交换console.log(a); console.log(b);复制代码es6 对象扩展[a,b][b,a];复制代码利用执行顺序aab; ba-b; aa-…

CS 320—Week 8 Homewor

CS 320—Week 8 Homework—Due W 3/27 11:59pmWrite your answers to the problems in the space indicated. Scan your solution and submitto Gradescope as a PDF file. You will receive an email about the Gradescope account.You may do this from your phone using fre…