1. 程式人生 > >【POJ 1741】 Tree

【POJ 1741】 Tree

兩個指針 href 題目 code cto pan -- class 我們

【題目鏈接】

http://poj.org/problem?id=1741

【算法】

點分治

要求距離不超過k的點對個數,不妨將路徑分成兩類 :

1. 經過根節點 2. 不經過根節點

考慮第1類路徑,不妨從根節點進行一次深度優先遍歷,求出每個點與根節點的距離,將距離排序,然後用兩個指針掃描一遍即可,註意要減掉多算的

然後,遞歸地計算子節點的第一類路徑,即可

但是這樣是會超時的,我們不妨每次選擇子樹的重心進行計算

這樣做法的時間復雜度存在上界 : O(Nlog^2N)

【代碼】

#include <algorithm>  
#include <bitset>  
#include <cctype>  
#include <cerrno>  
#include <clocale>  
#include <cmath>  
#include <complex>  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <ctime>  
#include 
<deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include
<ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; #define MAXN 10010 int i,n,k,tot,len,ans,root,u,v,w; int head[MAXN],weight[MAXN],size[MAXN],d[MAXN],dep[MAXN]; bool visited[MAXN]; struct Edge { int to,w,nxt; } e[MAXN<<1]; inline void addedge(int u,int v,int w) { tot++; e[tot] = (Edge){v,w,head[u]}; head[u] = tot; } inline void get_root(int u,int fa,int total) { int i,v; size[u] = 1; weight[u] = 0; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (v != fa && !visited[v]) { get_root(v,u,total); size[u] += size[v]; weight[u] = max(weight[u],size[v]); } } weight[u] = max(weight[u],total-size[u]); if (weight[u] < weight[root]) root = u; } inline void dfs(int u,int fa) { int i,v,w; d[++len] = dep[u]; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!visited[v] && v != fa) { dep[v] = dep[u] + w; dfs(v,u); } } } inline int calc(int u) { int i,j; int ret = 0; len = 0; dfs(u,0); i = 1; j = len; sort(d+1,d+len+1); while (i < j) { if (d[i] + d[j] <= k) { ret += j - i; i++; } else j--; } return ret; } inline void work(int u) { int i,v,w; dep[u] = 0; visited[u] = true; ans += calc(u); for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!visited[v]) { dep[v] = w; ans -= calc(v); root = 0; get_root(v,0,size[v]); work(root); } } } int main() { while (scanf("%d%d",&n,&k) != EOF && !(n == 0 && k == 0)) { memset(visited,false,sizeof(visited)); tot = 0; for (i = 1; i <= n; i++) head[i] = 0; for (i = 1; i < n; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } size[0] = weight[0] = n; root = 0; get_root(1,0,0); ans = 0; work(root); printf("%d\n",ans); } return 0; }

【POJ 1741】 Tree