ACM模板库

ACM模板库


点分治

<p>下面求树上小于等于k的路径数量(路径两端点不同)</p> <pre><code class="language-cpp">#include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;algorithm&gt; using namespace std; const int maxn = 1e5+5; typedef long long ll; typedef pair&lt;ll, int&gt; Edge; vector&lt;Edge&gt; mp[maxn]; int n, k; //siz表示子树大小,maxson表示重儿子子树的大小 int siz[maxn], maxson[maxn] = {maxn}, root; bool vis[maxn]; vector&lt;ll&gt; dis; int subn;//求根时子树大小 ll ans = 0; void getroot(int u, int fa){//n为树的大小,求重心 siz[u] = 1; maxson[u] = 0; for(int i = 0; i &lt; mp[u].size(); i++){ int v = mp[u][i].second; if(vis[v] || v == fa) continue; getroot(v, u); siz[u] = siz[u] + siz[v]; maxson[u] = max(maxson[u], siz[v]); } maxson[u] = max(maxson[u], subn - siz[u]); if(maxson[u] &lt; maxson[root]) root = u; } void getdis(int u, int fa, ll dist){ dis.push_back(dist); for(int i = 0; i &lt; mp[u].size(); i++){ int v = mp[u][i].second; if(vis[v] || v == fa) continue; getdis(v, u, dist + mp[u][i].first); } return; } int calc(int u, ll len){ //这个用来求解的函数,自定义 int cnt = 0; ll ans = 0; dis.clear(); getdis(u, 0, len); sort(dis.begin(), dis.end()); int l = 0, r = dis.size()-1; while(l &lt;= r){ if(dis[l] + dis[r] &lt;= k){ ans = ans + r - l; l++; } else r--; } return ans; } void divide(int u){ ans = ans + calc(u, 0); vis[u] = true; for(int i = 0; i &lt; mp[u].size(); i++){ int v = mp[u][i].second; if(vis[v]) continue; ans = ans - calc(v, mp[u][i].first); subn = siz[v]; root = 0; getroot(v, 0); divide(root); } return; } void init(){ subn = n; ans = 0; for(int i = 1; i &lt;= n; i++){ vis[i] = false; mp[i].clear(); } } int main(){ while(scanf("%d%d", &amp;n, &amp;k)){ if(n == 0 &amp;&amp; k == 0) return 0; init(); for(int i = 1; i &lt; n; i++){ int u, v; ll w; scanf("%d%d%lld", &amp;u, &amp;v, &amp;w); mp[u].push_back(Edge(w, v)); mp[v].push_back(Edge(w, u)); } getroot(1, 0); divide(root); cout &lt;&lt; ans &lt;&lt; endl; } } </code></pre>

页面列表

ITEM_HTML