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.pswp.cn/news/248303.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/248303.shtml
英文地址,請注明出處:http://en.pswp.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…