博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj1987 Distance Statistics
阅读量:6196 次
发布时间:2019-06-21

本文共 3208 字,大约阅读时间需要 10 分钟。

普通dfs访问每个点对的复杂度是O(n^2)的,显然会超时。

考虑访问到当前子树的根节点时,统计所有经过根的点(u, v)满足:

dist(u) + dist(v) <= maxd,并且

belong(u)≠belong(v)(即u,v不在同一子树)。

这里说的距离指的是节点到跟的距离。

可以用作差法,即用所有满足条件的点对数减去那些在根节点为当前子树根节点的儿子节点的点对数。

上面一步可以用O(nlogn)的复杂度解决,即先排序再比较。

根节点子树可以递归解决,用树的点分治。

总复杂度上界是O(nlognlogn)。

 

 

 

1 #include 
2 #include
3 #include
4 using namespace std; 5 const int maxn = 1e5 + 10; 6 const int inf = 0x3f3f3f3f; 7 struct Edge{ 8 int to, next, w; 9 }edge[maxn << 1]; 10 int head[maxn], N; 11 int n, m, maxd; 12 bool vis[maxn]; 13 int cnt[maxn]; 14 int maxi[maxn]; 15 int ans; 16 int mini, root, sum; 17 int buf[maxn], k; 18 19 void addEdge(int u, int v, int w){ 20 edge[N].next = head[u]; 21 edge[N].to = v; 22 edge[N].w = w; 23 head[u] = N++; 24 } 25 26 void init(){ 27 N = 0; 28 memset(head, -1, sizeof head); 29 } 30 31 void get_cnt(int u){ 32 cnt[u] = 1; 33 vis[u] = 1; 34 maxi[u] = -1; 35 buf[k++] = u; 36 for(int i = head[u]; i + 1; i = edge[i].next){ 37 int v = edge[i].to; 38 if(vis[v]) continue; 39 get_cnt(v); 40 cnt[u] += cnt[v]; 41 maxi[u] = max(maxi[u], cnt[v]); 42 } 43 vis[u] = 0; 44 } 45 46 void get_dist(int u, int d){ 47 vis[u] = 1; 48 buf[k++] = d; 49 for(int i = head[u]; i + 1; i = edge[i].next){ 50 int v = edge[i].to; 51 if(vis[v]) continue; 52 get_dist(v, d + edge[i].w); 53 } 54 vis[u] = 0; 55 } 56 57 int get_buf_sum(int left, int right){ 58 sort(buf + left, buf + right); 59 int tem = 0; 60 for(int i = right - 1, j = left; i >= left + 1; i--){ 61 while(j < i && buf[i] + buf[j] <= maxd) ++j; 62 tem += min(i, j) - left; 63 } 64 return tem; 65 } 66 67 void cal(int u){ 68 k = 0; 69 get_cnt(u); 70 mini = inf; 71 for(int i = 0; i < k; i++){ 72 int tem = max(cnt[u] - cnt[buf[i]], maxi[buf[i]]); 73 if(tem < mini) mini = tem, root = buf[i]; 74 } 75 k = 0; 76 vis[root] = 1; 77 int tem = 0; 78 for(int i = head[root]; i + 1; i = edge[i].next){ 79 int v = edge[i].to; 80 if(vis[v]) continue; 81 int pre = k; 82 get_dist(v, edge[i].w); 83 tem -= get_buf_sum(pre, k); 84 } 85 buf[k++] = 0; 86 tem += get_buf_sum(0, k); 87 ans += tem; 88 for(int i = head[root]; i + 1; i = edge[i].next){ 89 int v = edge[i].to; 90 if(vis[v]) continue; 91 cal(v); 92 } 93 } 94 95 void solve(){ 96 scanf("%d", &maxd); 97 memset(vis, 0, sizeof vis); 98 ans = 0; 99 for(int i = 1; i <= n; i++){100 if(!vis[i]) cal(i);101 }102 printf("%d\n", ans);103 }104 105 int main(){106 //freopen("in.txt", "r", stdin);107 while(~scanf("%d", &n)){108 scanf("%d", &m);109 init();110 for(int i = 0, x, y, z; i < m; i++){111 scanf("%d%d%d", &x, &y, &z);112 addEdge(x, y, z);113 addEdge(y, x, z);114 getchar(), getchar();115 }116 solve();117 }118 return 0;119 }
View Code

 

转载于:https://www.cnblogs.com/astoninfer/p/4882167.html

你可能感兴趣的文章
vmware10密钥
查看>>
curl上传图片的大坑
查看>>
用户态和内核态简析
查看>>
NancyFx 2.0的开源框架的使用-AspnetBootstrapping
查看>>
Netty In Action中文版 - 第十六章:从EventLoop取消注册和重新注册
查看>>
ERP选型及心得
查看>>
awk报告生成器
查看>>
Mysql多实例运行
查看>>
Python的pass语句
查看>>
inotifywait
查看>>
RIP协议
查看>>
Linux基础系列(五)Linux系统文件删除原理
查看>>
MVC5 DB FIRST
查看>>
文件与文件系统的压缩与打包
查看>>
磁盘的性能影响着mysql连接数(请使用火狐浏览器浏览本页面,否则图片不显示)...
查看>>
视野和希望的对话
查看>>
修改eclipse默认工作空间和删除工作空间
查看>>
Egret之EUI及龙骨基础
查看>>
Ubuntu16.04安装Docker 入门
查看>>
有限算法下的技术实现路线
查看>>