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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[AHOI2008] 紧急集合

發(fā)布時間:2024/4/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [AHOI2008] 紧急集合 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Description

歡樂島上有個非常好玩的游戲,叫做“緊急集合”。在島上分散有N個等待點,有N-1條道路連接著它們,每一條道路都連接某兩個等待點,且通過這些道路可以走遍所有的等待點,通過道路從一個點到另一個點要花費一個游戲幣。

參加游戲的人三人一組,開始的時候,所有人員均任意分散在各個等待點上(每個點同時允許多個人等待),每個人均帶有足夠多的游戲幣(用于支付使用道路的花費)、地圖(標(biāo)明等待點之間道路連接的情況)以及對話機(用于和同組的成員聯(lián)系)。當(dāng)集合號吹響后,每組成員之間迅速聯(lián)系,了解到自己組所有成員所在的等待點后,迅速在N個等待點中確定一個集結(jié)點,組內(nèi)所有成員將在該集合點集合,集合所用花費最少的組將是游戲的贏家。

小可可和他的朋友邀請你一起參加這個游戲,由你來選擇集合點,聰明的你能夠完成這個任務(wù),幫助小可可贏得游戲嗎?

Input

第一行兩個正整數(shù)N和M(N<=500000,M<=500000),之間用一個空格隔開。分別表示等待點的個數(shù)(等待點也從1到N進行編號)和獲獎所需要完成集合的次數(shù)。 隨后有N-1行,每行用兩個正整數(shù)A和B,之間用一個空格隔開,表示編號為A和編號為B的等待點之間有一條路。 接著還有M行,每行用三個正整數(shù)表示某次集合前小可可、小可可的朋友以及你所在等待點的編號。

Output

一共有M行,每行兩個數(shù)P,C,用一個空格隔開。其中第i行表示第i次集合點選擇在編號為P的等待點,集合總共的花費是C個游戲幣。

說明

\(100\%\)的數(shù)據(jù)中,\(N\leq500000\)\(M\leq500000\)

Solution

這題就差在說明里寫上“這是一道性質(zhì)題,推出來性質(zhì)你就能A,不然就乖乖打暴力吧!”

首先能觀察到的是這三個點之間兩兩的 \(lca\) 只能是兩個點或更少

也就是說,必定有至少兩對點是同一個 \(lca\)

這啟發(fā)我們從 \(lca\) 入手推性質(zhì)。

手玩幾組數(shù)據(jù)發(fā)現(xiàn)答案就是三個 \(lca\) 中深度較淺的那個。

所以直接求出這三個 \(lca\) 然后暴力求距離即可

但是正解好像是再推一下式子,發(fā)現(xiàn)無論如何 \[ans=dep[x]+dep[y]+dep[z]-dep[lca(x,y)]-dep[lca(x,z)]-dep[lca(y,z)]\].

求距離都不用,直接減就行了。

#include<cstdio> #include<cctype> #define N 500005 #define min(A,B) ((A)<(B)?(A):(B)) #define swap(A,B) ((A)^=(B)^=(A)^=(B))int dfn[N],top[N],d[N]; int n,m,cnt,tot,sum[N<<2]; int fa[N],sze[N],son[N],head[N];struct Edge{int to,nxt; }edge[N<<1];void add(int x,int y){edge[++cnt].to=y;edge[cnt].nxt=head[x];head[x]=cnt; }int getint(){int x=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();return x; }void first_dfs(int now){sze[now]=1;for(int i=head[now];i;i=edge[i].nxt){int to=edge[i].to;if(sze[to])continue;fa[to]=now;d[to]=d[now]+1;first_dfs(to);sze[now]+=sze[to];if(sze[to]>sze[son[now]])son[now]=to;} }void second_dfs(int now,int low){top[now]=low;dfn[now]=++tot;if(son[now])second_dfs(son[now],low);for(int i=head[now];i;i=edge[i].nxt){int to=edge[i].to;if(to==fa[now] or to==son[now])continue;second_dfs(to,to);} }int query(int cur,int l,int r,int ql,int qr){if(ql<=l and r<=qr)return r-l+1;int mid=l+r>>1,ans=0;if(ql<=mid)ans+=query(cur<<1,l,mid,ql,qr);if(mid<qr)ans+=query(cur<<1|1,mid+1,r,ql,qr);return ans; }int lca(int x,int y){while(top[x]!=top[y]){if(d[top[x]]<d[top[y]])swap(x,y);x=fa[top[x]];}if(d[x]<d[y])swap(x,y);return y; }int ask(int x,int y){int ans=0;while(top[x]!=top[y]){if(d[top[x]]<d[top[y]])swap(x,y);ans+=query(1,1,n,dfn[top[x]],dfn[x]);x=fa[top[x]];}if(d[x]<d[y])swap(x,y);if(x!=y)ans+=query(1,1,n,dfn[y]+1,dfn[x]);return ans; }signed main(){n=getint(),m=getint();for(int i=1;i<n;i++){int x=getint(),y=getint();add(x,y);add(y,x);}d[1]=1; first_dfs(1);second_dfs(1,1);while(m--){int a=getint(),b=getint(),c=getint();int x=lca(a,b),y=lca(a,c),z=lca(b,c);int ans=d[a]+d[b]+d[c]-d[x]-d[y]-d[z];if(d[x]>=d[y] and d[x]>=d[z])printf("%d %d\n",x,ans);else if(d[y]>=d[x] and d[y]>=d[z])printf("%d %d\n",y,ans);else if(d[z]>=d[x] and d[z]>=d[y])printf("%d %d\n",z,ans);/*int a=getint(),b=getint(),c=getint();int x=lca(a,b);int y=lca(a,c);if(x!=y){if(d[x]<d[y]){int ans=d[a]+d[c]-2*d[y];ans+=ask(b,y);printf("%d %d\n",y,ans);} else{int ans=d[a]+d[b]-2*d[x];ans+=ask(c,x);printf("%d %d\n",x,ans);}} else{int z=lca(b,c);if(z==x){int ans=d[a]+d[b]+d[c]-3*d[z];printf("%d %d\n",z,ans);} else{if(d[x]<d[z]){int ans=d[b]+d[c]-2*d[z];ans+=ask(a,z);printf("%d %d\n",z,ans);} else{int ans=d[a]+d[b]-2*d[x];ans+=ask(c,x);printf("%d %d\n",x,ans);}}}*/}return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/YoungNeal/p/9161763.html

超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的[AHOI2008] 紧急集合的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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