模板:(樹剖\(lca\)+建虛樹)
找最小邊權就是記錄一下最小值和次小值,然後更新 \(ans\)#include using namespace std;
const int maxn=100000+10;
int n,m,dp[maxn],vis[maxn],h[maxn],sta[maxn],top;
int fir[maxn],head[maxn],to[maxn<<1],nxt[maxn<<1],tot,cnt;
int top[maxn],dep[maxn],id[maxn],siz[maxn],son[maxn],fa[maxn],tim;
struct nodee[maxn<<1];
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}inline void add(int x,int y)
inline void addedge(int x,int y)
void dfs1(int x,int f)
bool cmp(int a,int b)val_)\),其中 \(val\) 為邊權。
\(code\ below:\)
#include #define int long long
using namespace std;
const int maxn=250000+10;
const int inf=1e18;
int n,m,dp[maxn],dis[maxn],vis[maxn],h[maxn],sta[maxn],top;
int fir[maxn],head[maxn],to[maxn<<1],nxt[maxn<<1],tot,cnt;
int top[maxn],dep[maxn],id[maxn],siz[maxn],son[maxn],fa[maxn],tim;
struct nodee[maxn<<1];
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}inline void add(int x,int y,int w)
inline void addedge(int x,int y)
void dfs1(int x,int f)
bool cmp(int a,int b)
ans-=2*now*dep[x];
if(vis[x]) ans-=2*sub[x]*dep[x],sub[x]++;
}
找最大邊權同個道理
int dfs_min(int x)
if(vis[x]&&min!=inf) ans=min(ans,min-dep[x]);
if(min!=inf&&sec!=inf) ans=min(ans,min+sec-2*dep[x]);
if(vis[x]) min=dep[x];
return min;
}int dfs_max(int x)e[maxn<<1];
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}inline void add(int x,int y)
inline void addedge(int x,int y)
void dfs1(int x,int f)
bool cmp(int a,int b)
if(vis[x]&&min!=inf) ans=min(ans,min-dep[x]);
if(min!=inf&&sec!=inf) ans=min(ans,min+sec-2*dep[x]);
if(vis[x]) min=dep[x];
return min;
}int dfs_max(int x) dp[son]\)
2、\(vis[x]=0,sum>1\),那就直接選 \(x\),\(x\) 的子樹已經被 \(x\) 封死了
3、\(vis[x]=0,sum\leq 1\),那就傳到 \(x\) 的父親上,讓 \(x\) 的父親解決好了
\(code\ below:\)
#include using namespace std;
const int maxn=100000+10;
int n,m,dp[maxn],vis[maxn],h[maxn],sta[maxn],top;
int fir[maxn],head[maxn],to[maxn<<1],nxt[maxn<<1],tot,cnt;
int top[maxn],dep[maxn],id[maxn],siz[maxn],son[maxn],fa[maxn],tim;
struct nodee[maxn<<1];
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}inline void add(int x,int y)
inline void addedge(int x,int y)
void dfs1(int x,int f)
bool cmp(int a,int b)
int main()
dfs1(1,0);dfs2(1,1);
m=read();
for(int t=1;t<=m;t++)
flag=0;
for(int i=1;i<=k;i++)
flag|=vis[fa[h[i]]];
if(flag)
sort(h+1,h+k+1,cmp);
cnt=0;sta[top=1]=1;
for(int i=1;i<=k;i++)
addedge(sta[top-1],sta[top]);
top--;
}if(sta[top]!=h[i]) sta[++top]=h[i];
} while(--top) addedge(sta[top],sta[top+1]);
printf("%d\n",dfs(1));
for(int i=1;i<=k;i++) vis[h[i]]=0;
}return 0;
}
虛樹學習筆記
將關鍵點按dfs序排序後,所有關鍵點與相鄰關鍵點的lca合起來構成虛樹 通常還要加上整棵樹的根 虛樹至多有2k2k 個點。體現在實現中就是每次都pop若干點,並有機會push2個點。stk中存的是從根到當前點的遞迴棧中目前選入虛樹的點。stk中的點之間都未連邊 因為事實上關係還未確定 pop掉乙個點...
虛樹 學習筆記
水平不夠,學習來湊 又開了個天大的新坑 sdoi 2011 消耗戰 題目大意就是講 給出一棵樹,有邊權,然後給出k個查詢點,問從1號店不能到任何乙個查詢點的代價是多少.先考慮一下樹形動歸.dp i 表示從1不能到以i為根的子樹中的所有查詢點的最小代價 考慮維護乙個量,mins i 表示從1到i路徑最...
虛樹學習筆記
虛樹常常被使用在樹形 dp 中。有些時候,我們需要計算的節點僅僅是一棵樹中的某幾個節點 這個時候如果對整棵樹都進行一次計算開銷太大了 所以我們需要把這些節點從原樹中抽象出來 按照它們在原樹中的關係重新建一棵樹,這樣的樹就是虛樹 在構建之前,我們需要把所有需要加入的節點按照 dfn 序從小到大排好序 ...