生活随笔
收集整理的這篇文章主要介紹了
【BZOJ3611】【HeOI2014】—大工程(虚树+dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
首先肯定建出虛樹
考慮三種答案如何分別統計
路徑長度和顯然示是對于每條邊考慮一下上下有多少個點,乘一下就可以了
最大值顯然就是樹的直徑
最小值可以考慮樹形dpdpdp,考慮mn[i]mn[i]mn[i]表示iii到其子樹中最近的距離
顯然可以類似直徑樹形dpdpdp解決
#include<bits/stdc++.h>
using namespace std
;
#define ll long long
inline int read(){char ch
=getchar();int res
=0,f
=1;while(!isdigit(ch
)){if(ch
=='-')f
=-f
;ch
=getchar();}while(isdigit(ch
))res
=(res
+(res
<<2)<<1)+(ch
^48),ch
=getchar();return res
*f
;
}
const int N
=1000005;
const ll inf
=1e9;
namespace T
{int adj
[N
],nxt
[N
<<1],to
[N
<<1],cnt
,siz
[N
],dfn
[N
],tot
,son
[N
],top
[N
],fa
[N
],dep
[N
];inline void addedge(int u
,int v
){nxt
[++cnt
]=adj
[u
],adj
[u
]=cnt
,to
[cnt
]=v
;}void dfs1(int u
){siz
[u
]=1;for(int e
=adj
[u
];e
;e
=nxt
[e
]){int v
=to
[e
];if(v
==fa
[u
])continue;fa
[v
]=u
,dep
[v
]=dep
[u
]+1;dfs1(v
),siz
[u
]+=siz
[v
];if(siz
[v
]>siz
[son
[u
]])son
[u
]=v
;}}void dfs2(int u
,int tp
){dfn
[u
]=++tot
,top
[u
]=tp
;if(son
[u
])dfs2(son
[u
],tp
);for(int e
=adj
[u
];e
;e
=nxt
[e
]){int v
=to
[e
];if(v
==fa
[u
]||v
==son
[u
])continue;dfs2(v
,v
);}}inline int Lca(int u
,int v
){while(top
[u
]!=top
[v
]){if(dep
[top
[u
]]<dep
[top
[v
]])swap(u
,v
);u
=fa
[top
[u
]];}return dep
[u
]>dep
[v
]?v
:u
;}
};
int n
,adj
[N
],nxt
[N
<<1],to
[N
<<1],cnt
,q
,a
[N
],stk
[N
],top
,k
,vis
[N
],siz
[N
],ans2
,ans3
,mx
[N
],mn
[N
];
ll ans1
;
inline void addedge(int u
,int v
){nxt
[++cnt
]=adj
[u
],adj
[u
]=cnt
,to
[cnt
]=v
;
}
inline bool comp(const int &a
,const int &b
){return T
::dfn
[a
]<T
::dfn
[b
];
}
inline void chemn(int &a
,int b
){a
=a
>b
?b
:a
;
}
inline void chemx(int &a
,int b
){a
=a
>b
?a
:b
;
}
void dp(int u
){mx
[u
]=0,mn
[u
]=inf
,siz
[u
]=vis
[u
];for(int e
=adj
[u
];e
;e
=nxt
[e
]){int v
=to
[e
];int d
=T
::dep
[v
]-T
::dep
[u
];dp(v
),siz
[u
]+=siz
[v
];ans1
+=1ll*siz
[v
]*(k
-siz
[v
])*d
;chemn(ans2
,mn
[u
]+mn
[v
]+d
),chemn(mn
[u
],mn
[v
]+d
);chemx(ans3
,mx
[u
]+mx
[v
]+d
),chemx(mx
[u
],mx
[v
]+d
);}if(vis
[u
])chemn(ans2
,mn
[u
]),chemx(ans3
,mx
[u
]),mn
[u
]=0;adj
[u
]=0;
}
inline void work(){top
=0,cnt
=0;for(int i
=1;i
<=k
;i
++){if(!top
){stk
[++top
]=a
[i
];continue;}int lca
=T
::Lca(stk
[top
],a
[i
]);while(T
::dfn
[lca
]<T
::dfn
[stk
[top
]]){if(T
::dfn
[lca
]>=T
::dfn
[stk
[top
-1]]){addedge(lca
,stk
[top
]);if(stk
[--top
]!=lca
)stk
[++top
]=lca
;break;}addedge(stk
[top
-1],stk
[top
]),top
--;}stk
[++top
]=a
[i
];}while(top
>1)addedge(stk
[top
-1],stk
[top
]),top
--;ans1
=0,ans2
=inf
,ans3
=0,dp(stk
[1]);for(int i
=1;i
<=k
;i
++)vis
[a
[i
]]=0;cout
<<ans1
<<" "<<ans2
<<" "<<ans3
<<'\n';
}
int main(){n
=read();for(int i
=1;i
<n
;i
++){int u
=read(),v
=read();T
::addedge(u
,v
),T
::addedge(v
,u
);}T
::dfs1(1),T
::dfs2(1,1);q
=read();for(int i
=1;i
<=q
;i
++){k
=read();for(int j
=1;j
<=k
;j
++)a
[j
]=read(),vis
[a
[j
]]=1;sort(a
+1,a
+k
+1,comp
),work();}
}
轉載于:https://www.cnblogs.com/stargazer-cyk/p/11145614.html
總結
以上是生活随笔為你收集整理的【BZOJ3611】【HeOI2014】—大工程(虚树+dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。