日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[WC2018]通道

發(fā)布時(shí)間:2025/5/22 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [WC2018]通道 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目描述

http://uoj.ac/problem/347

題解

解法1

求三棵樹(shù)的直徑,看起來(lái)非常不可做,但是所有邊權(quán)都是正的,可以讓我們想到爬山。

所以我們可以按照BFS求樹(shù)的直徑的方法,隨機(jī)一個(gè)點(diǎn)作為起點(diǎn),然后BFS一遍,找到在這三棵樹(shù)的意義下最遠(yuǎn)的那個(gè)點(diǎn),然后繼續(xù)爬山。

因?yàn)檫@樣做沒(méi)啥正確性,所以再卡一下時(shí)間就好了。

代碼

#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<ctime> #define get_clock (double)clock()/(double)CLOCKS_PER_SEC*1000.0 #define N 100009 using namespace std; typedef long long ll; ll dis[3][N],n,ans; bool vis[N]; inline ll rd(){ll x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x; } struct Edge{int head[N],tot;struct ljb{int n,to;ll l;}e[N<<1];inline void add(int u,int v,ll l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;} }edge[3]; void dfs(int u,int fa,int tag){for(int i=edge[tag].head[u];i;i=edge[tag].e[i].n)if(edge[tag].e[i].to!=fa){int v=edge[tag].e[i].to;dis[tag][v]=dis[tag][u]+edge[tag].e[i].l;dfs(v,u,tag);} } void BF(){for(int x=1;x<=n;++x){dis[0][x]=dis[1][x]=dis[2][x]=0;dfs(x,0,0);dfs(x,0,1);dfs(x,0,2);for(int i=1;i<=n;++i){ans=max(ans,dis[0][i]+dis[1][i]+dis[2][i]);} } } int main(){srand(19260817);double start=get_clock;n=rd();ll u,v,w;for(int i=1;i<n;++i){u=rd();v=rd();w=rd();edge[0].add(u,v,w);}for(int i=1;i<n;++i){u=rd();v=rd();w=rd();edge[1].add(u,v,w);}for(int i=1;i<n;++i){u=rd();v=rd();w=rd();edge[2].add(u,v,w);}if(n<=3000){BF();}else{while(get_clock-start<=3500){int x=rand()%n+1;while(vis[x])x=rand()%n+1;for(int j=1;j<=9;++j){if(vis[x])break;vis[x]=1;dis[0][x]=dis[1][x]=dis[2][x]=0;dfs(x,0,0);dfs(x,0,1);dfs(x,0,2);ll now=0;for(int i=1;i<=n;++i){ll num=dis[0][i]+dis[1][i]+dis[2][i];ans=max(ans,num);if(num>now){now=num;if(!vis[i])x=i;}} } }}cout<<ans;return 0; }

這樣做可以通過(guò)官方數(shù)據(jù),但是在UOJ上會(huì)被HACK。

解法2

我們考慮對(duì)第一棵樹(shù)邊分治,設(shè)當(dāng)前的重心邊為i。

那么我們需要最大化的東西就是deep1[x]+deep1[y]+val[i]+dist2(x,y)+dist3(x,y)。

其中xy是當(dāng)前邊分的塊內(nèi)點(diǎn),且分居在i的兩側(cè),我們可以設(shè)兩邊的顏色為黑色和白色。

這樣我們相當(dāng)于給x和y加上了一個(gè)權(quán),并且去掉了第一棵樹(shù)的LCA的限制。

而且val的影響可以先不討論了。

然后我們考慮對(duì)第二顆樹(shù)對(duì)目前邊分的點(diǎn)建立虛樹(shù)。

令value[x]表示deep1[x]+deep2[x]

然后我們?cè)赿fs虛樹(shù)的時(shí)候枚舉LCA,那么此時(shí)我們要最大化的東西就是value[x]+value[y]-2*deep2[lca]+dist3(x,y),需滿足x和y在LCA的不同子樹(shù)中。

然后最后的是個(gè)常數(shù),而不用管。

然后value[x]+value[y]+dist3(x,y)這個(gè)東西,有點(diǎn)像樹(shù)的直徑。

我們可以想象一下,在第三棵樹(shù)上的每一個(gè)點(diǎn)i我們都往外連出一條出邊連向i',邊權(quán)為value[i],這樣上面的東西就變成了樹(shù)的直徑問(wèn)題。

有一個(gè)結(jié)論,有兩個(gè)點(diǎn)集,每個(gè)點(diǎn)集的直徑為x-y,那么跨越兩個(gè)點(diǎn)集的直徑的兩個(gè)端點(diǎn)一定在那兩個(gè)點(diǎn)集的端點(diǎn)中出現(xiàn)過(guò)。

這個(gè)結(jié)論在邊權(quán)非負(fù)的條件下成立。

所以我們對(duì)黑白兩個(gè)點(diǎn)集分別維護(hù)直徑,在子樹(shù)合并的時(shí)候更新答案就好了。

其實(shí)想到這里,這道題就不難了,就是碼量有點(diǎn)大。

ZZ錯(cuò)誤:求LCA倍增寫(xiě)錯(cuò),合并直徑時(shí)沒(méi)有考慮只有一個(gè)點(diǎn)的情況。

代碼

#include<iostream> #include<cstdio> #include<vector> #include<algorithm> #include<cmath> #define inf 1e18 #define N 100009 using namespace std; typedef long long ll; int dfn[N],s,n,NTT; inline ll rd(){ll x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x; } struct node{int tag,x;ll y;inline bool operator <(const node &b)const{return dfn[x]<dfn[b.x];} }a[N]; namespace T3{int head[N],tot,p[20][N<<1],tag[N],lo[N<<1];ll dis[N];struct edge{int n,to;ll l;}e[N<<1];inline void add(int u,int v,ll l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;}void dfs(int u,int fa){p[0][++tag[0]]=u;tag[u]=tag[0];for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){int v=e[i].to;dis[v]=dis[u]+e[i].l;dfs(v,u);p[0][++tag[0]]=u;}}inline int great(int x,int y){return tag[x]>tag[y]?y:x;}inline int getlca(int u,int v){int x=tag[u],y=tag[v];if(x>y)swap(x,y);int llo=lo[y-x+1];return great(p[llo][x],p[llo][y-(1<<llo)+1]);}inline void prework(){dfs(1,0);for(int i=1;(1<<i)<=tag[0];++i)for(int j=1;j<=tag[0];++j)p[i][j]=great(p[i-1][j],p[i-1][j+(1<<i-1)]);///!!!!for(int i=2;i<=tag[0];++i)lo[i]=lo[i>>1]+1;}inline ll calc(int x,int y){return dis[x]+dis[y]-2*dis[getlca(x,y)];} } namespace T2{int head[N],tot,p[20][N<<1],tag[N],lo[N<<1],vis[N],st[N],top,rbs[N];ll dis[N],val[N],ans;vector<int>::iterator it;vector<int>vec[N];struct edge{int n,to;ll l;}e[N<<1];inline void add(int u,int v,ll l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;}struct DP{int x[2];inline bool empty(int x,int y){return (!x&&!y);}inline void clear(){x[0]=x[1]=0;}}dp[N][3];void dfs(int u,int f){p[0][++tag[0]]=u;tag[u]=tag[0];dfn[u]=++dfn[0];for(int i=head[u];i;i=e[i].n)if(e[i].to!=f){int v=e[i].to;dis[v]=dis[u]+e[i].l;dfs(v,u);p[0][++tag[0]]=u;}} inline int great(int x,int y){return tag[x]>tag[y]?y:x;}inline int getlca(int u,int v){int x=tag[u],y=tag[v];if(x>y)swap(x,y);int llo=lo[y-x+1];return great(p[llo][x],p[llo][y-(1<<llo)+1]);}inline void prework(){dfs(1,0); for(int i=1;(1<<i)<=tag[0];++i)for(int j=1;j+(1<<i)-1<=tag[0];++j)p[i][j]=great(p[i-1][j],p[i-1][j+(1<<i-1)]);for(int i=2;i<=tag[0];++i)lo[i]=lo[i>>1]+1;}inline ll calc(int x,int y){if(!x||!y)return -inf;return val[x]+val[y]+T3::calc(x,y);}void ddp(int u){if(vis[u])dp[u][vis[u]].x[0]=u;for(int i=0;i<vec[u].size();++i){int v=vec[u][i];ddp(v);for(int i=1;i<=2;++i)for(int j=0;j<2;++j)for(int k=0;k<2;++k){int d=i==1?2:1,x=dp[u][i].x[j],y=dp[v][d].x[k];ans=max(ans,calc(x,y)-2ll*dis[u]);}for(int i=1;i<=2;++i){if(!dp[u][i].x[0]&&!dp[u][i].x[1]){dp[u][i].x[0]=dp[v][i].x[0];dp[u][i].x[1]=dp[v][i].x[1];continue;}if(!dp[v][i].x[0]&&!dp[v][i].x[1])continue;int maxx=dp[u][i].x[0],maxy=dp[u][i].x[1];ll you=calc(maxx,maxy),bian=calc(dp[v][i].x[0],dp[v][i].x[1]);if(bian>you)maxx=dp[v][i].x[0],maxy=dp[v][i].x[1],you=bian;for(int j=0;j<2;++j)for(int k=0;k<2;++k){int x=dp[u][i].x[j],y=dp[v][i].x[k];bian=calc(x,y);if(bian>you)you=bian,maxx=x,maxy=y;}dp[u][i].x[0]=maxx;dp[u][i].x[1]=maxy;}}}inline ll work(){ans=-inf;sort(a+1,a+s+1);for(int i=1;i<=s;++i){vis[a[i].x]=a[i].tag;val[a[i].x]=a[i].y+dis[a[i].x];}int start=1;st[top=1]=rbs[rbs[0]=1]=1;if(a[1].x==1)start++;for(int i=start;i<=s;++i){int x=a[i].x,lc=getlca(x,st[top]);if(lc==st[top]){st[++top]=x;rbs[++rbs[0]]=x;continue;}while(top>1){int xx=st[top],yy=st[top-1];if(dfn[yy]<=dfn[lc]){vec[lc].push_back(xx);top--;break;}vec[yy].push_back(xx);top--;} if(st[top]!=lc){st[++top]=lc;rbs[++rbs[0]]=lc;}if(st[top]!=x){st[++top]=x;rbs[++rbs[0]]=x;}}while(top>1){vec[st[top-1]].push_back(st[top]);top--;}ddp(1);while(rbs[0]){int x=rbs[rbs[0]];vis[x]=0;val[x]=0;vec[x].clear();dp[x][1].clear();dp[x][2].clear();rbs[0]--;}s=0;return ans;} } namespace T1{int head[N<<1],tot,num,size[N<<1],sum,nowroot,root,ga;bool jin[N<<2];ll deep[N<<1],ans;struct edge{int n,to;ll l;}e[N<<2];vector<int>vec[N];vector<ll>val[N];inline void add(int u,int v,ll l){vec[u].push_back(v);val[u].push_back(l);}vector<int>::iterator it;inline void add2(int u,int v,ll l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;}void dfs(int u,int fa){int now=0;for(int i=0;i<vec[u].size();++i){int v=vec[u][i];ll va=val[u][i];if(v==fa)continue;dfs(v,u);if(!now){add2(u,v,va);now=u;}else{++num;add2(now,num,0);add2(num,v,va);now=num;}}}void getroot(int u,int fa){size[u]=1;for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!jin[i]){int v=e[i].to;getroot(v,u);size[u]+=size[v];if(max(size[v],sum-size[v])<nowroot){nowroot=max(size[v],sum-size[v]);root=i;ga=size[v];}}}void getdeep(int u,int fa,int tag){if(u<=n)a[++s]=node{tag,u,deep[u]};for(int i=head[u];i;i=e[i].n)if(!jin[i]&&e[i].to!=fa){int v=e[i].to;deep[v]=deep[u]+e[i].l;getdeep(v,u,tag);}}void solve(int now,int sm){if(sm==1)return;root=tot+1;nowroot=2e9;sum=sm;getroot(now,0);jin[root]=jin[root^1]=1;int x=e[root].to,y=e[root^1].to,sumx=ga,sumy=sm-ga;deep[x]=0;deep[y]=0;getdeep(x,y,1);getdeep(y,x,2);ans=max(T2::work()+e[root].l,ans);solve(x,sumx);solve(y,sumy);}inline void work(){num=n;tot=1;dfs(1,0);solve(1,num);printf("%lld",ans);} } int main(){n=rd();int u,v;ll w;for(int i=1;i<n;++i){u=rd();v=rd();w=rd();T1::add(u,v,w);T1::add(v,u,w);}for(int i=1;i<n;++i){u=rd();v=rd();w=rd();T2::add(u,v,w);T2::add(v,u,w);}for(int i=1;i<n;++i){u=rd();v=rd();w=rd();T3::add(u,v,w);T3::add(v,u,w); }T3::prework();T2::prework();T1::work();return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/ZH-comld/p/10388820.html

總結(jié)

以上是生活随笔為你收集整理的[WC2018]通道的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲无圣光 | 日本高清中文字幕 | 亚洲乱码国产乱码精品精的特点 | 国产99久久久 | 中文字幕乱码人妻一区二区三区 | 91在线视频免费观看 | 亚洲图片88 | 日韩白浆 | 亚洲a影院 | 欧美操操操| 久久中文娱乐网 | 中文字幕人妻丝袜二区 | 欧美激情一二三区 | 日韩中文字幕在线观看视频 | 欧美日韩在线成人 | 色黄啪啪网| 免费日韩一级片 | 波多野结衣激情视频 | 国产亚洲精品精品国产亚洲综合 | 免费在线观看av网址 | 黄色大片儿 | 中文字幕一级二级三级 | 四虎少妇做爰免费视频网站四 | 欧美极品在线播放 | 国产乱码在线观看 | 久久久精品影视 | 日本在线一| 久久叉| 久久精品噜噜噜成人88aⅴ | 成人av电影在线播放 | 日韩欧美的一区二区 | 少妇特黄一区二区 | 97夜夜 | 久久久久人妻一区 | 99热这里只有精品9 日韩综合在线 | 成人动漫在线观看视频 | 成年人视频免费看 | 精品人妻一区二区三区蜜桃视频 | 色综合成人 | 懂色aⅴ一区二区三区免费 国产精品99在线观看 | 日本免费一区二区三区最新 | 成人国产精品久久 | 天堂国产一区二区三区 | 91色漫| 韩国一区二区三区视频 | 国产三级国产精品国产国在线观看 | 欧美疯狂做受 | 日韩在线观看网站 | 欧美成人69 | 九九热视频在线免费观看 | 啪啪网页 | 中文国产在线观看 | 一卡二卡国产 | 欧美一区二区视频免费观看 | 日本精品久久久久 | 日韩视频二区 | 国产精品久久久久久婷婷天堂 | 日韩av片在线播放 | 久久久久国产 | 欧美人与野 | 韩国三级中文字幕hd久久精品 | 捆绑调教视频网站 | 黄色片在线免费观看视频 | www国产精品内射熟女 | 亚洲高清在线观看 | 欧美日韩国产高清视频 | 亚洲色图少妇 | 97影音| 免费人成网站 | 亚洲一区二区精品 | 高清国产mv在线观看 | 久久精品免费在线 | jizz18欧美18 | 精品国产乱码久久久久久108 | 少妇又色又紧又大爽又刺激 | 日本黄色大片在线观看 | 日韩69| av美国| 国产精品嫩草69影院 | 国产青青草在线 | a级片中文字幕 | 韩国av电影在线观看 | 国产精品普通话 | 无码人妻精品一区二区三区在线 | 国产第一区第二区 | 久久影院午夜理论片无码 | 亚洲国产日韩精品 | 亚洲激情婷婷 | 日本h视频在线观看 | 午夜影院黄色 | 少妇搡bbbb搡bbb搡小说 | 日韩成人一区二区视频 | 日韩女同互慰一区二区 | 国产一区二区三区视频在线观看 | 亚洲 欧美 精品 | 日本xxxx高清| 免费观看一区二区三区 | 成人网战 | 欧美性生活在线视频 |