題面
題意:給你3000棵環套樹,邊長都為1,問兩個點的最短距離的最大值。
根據環套樹的套路,先把環找出來,然後dfs每棵外向樹。對於每個點,記錄l1為該點向下最長鏈的深度,l2為為該點向下次長鏈的深度,l1+l2就可能成為答案。這樣就處理了路徑在每棵樹上的情況。
我們考慮路徑跨越了環的情況。想到在吃雞時跑毒的短邊原則,最短路肯定在環的小半圈。
設環的長度為len,對於環上的第i個點和第j個點,j>i,最長路徑為
l1[i]+l1[j]+min(j-i,len-j+i)。
我們把min拆出來,就等價於把環複製一遍,對於點i,和它的前len/2個點計算距離,距離為l1[i]+l1[j]+i-j。就是求乙個滑動區間的l1[j]-j的最大值,就是乙個單調佇列了。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long ll;
const int n=3030;
int n,m,u[n],v[n];
int to[n*2],nex[n*2],head[n],cnt;
int fa[n],l1[n],l2[n],c[2
*n],num;
int ans;
bool cir[n],vis[n];
intq[2*n];
void add(int u,int v)
void dfs2(int
x) else
if(l1[to[h]]+1>l2[x])
l2[x]=l1[to[h]]+1;
}ans=max(ans,l1[x]+l2[x]);
}void dfs(int
x) c[++num]=to[h];
cir[to[h]]=1;
for(int i=1;i<=num;i++)
dfs2(c[i]);
return;
}fa[to[h]]=x;
dfs(to[h]);
}}int get(int
x)int main()
for(int i=num+1;i<=num*2;i++)
printf("%d\n",ans);
}return
0;}
昨晚看完了《我女友與…的慘烈…》,可能是我太喜歡夏川真涼了,整晚都感覺好虐,然後我今天就壞掉了。
kisekiより,約束が好き
2017 5 11 道路修建 思考記錄
這個線段樹一眼秒了 主要是有前面的思考經驗 就是維護兩個列對應線段上的形態。比較好想的 但資料結構題有個特點 使你知道結構也不會做 會做也會很大概率爆零.所以資料結構題必須 小資料 特殊資料 對拍!不然怎麼掛的都不知道 敲 錯 調 查 調 搞了乙個上午 這個題用線段樹維護 乙個最小值 合併時需要考慮...
bzoj2435 道路修建
道路修建 題目背景 bzoj2435 分析 暴力 dfs 突如其來的傻題 get 直接 dfs,每乙個點對答案的貢獻是,abs n size cur size cur w w 為這個點與父親的連邊的權值 然後就沒有然後了 source created by scarlyw include inclu...
cumtoj修建道路 LCA倍增
題目描述 n nn個點n 1 n 1n 1條邊,點之間兩兩連通,每次詢問3 33個點,求使這3 33個點連通的最小花費。1 n q 1 05 1 leq n,q leq 10 5 1 n,q 105 因為給的是一顆樹,最終的答案就是dis t x,y d ist y,z dis t x,z 2.fr...