How far away ? HDU
来源:互联网 发布:马家军调查知乎 编辑:程序博客网 时间:2024/05/01 15:17
题意:给你n个村庄,n-1条路将所有村庄联通,每条路都有自己的长度。m次提问,问a,b村庄之间路的长度。
分析:这个就是在一棵树上求两个点的距离嘛。LCA。因为数据范围比较小,暴力的话,每组时间复杂度为m*q,可以卡过去。
用Tarjan的话,每组时间复杂度为m+q,用Tarjan求LCA是一种离线做法,先把所有询问都存起来,然后相同起点的可以一起算。
d[i]:从根到i点的距离
f[i]:i的祖先
vis[i]:标记数组
edge[i]:存边
q[i]:存询问
col[i]:标记目前哪些点可以直接查找
主要的是并查集的使用~妙呀~
(PE是什么鬼,OUTPUT中说每组样例结束后空一行嘛,空了PE。。。不空A了。。
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <vector>#include <set>#include <map>using namespace std;#define ll long long#define mem(a,b) memset(a,b,sizeof(a))const int maxn = 4e4+10;struct node{ int to,pre,id,v;}edge[maxn*2];node q[maxn];int f[maxn],head[maxn],hq[maxn],vis[maxn],col[maxn];ll ans[maxn],d[maxn];void init(int n){ mem(edge,0);mem(vis,0);mem(head,-1);mem(hq,-1);mem(q,0);mem(col,0);mem(d,0); for(int i=1;i<=n;i++) f[i]=i;}int h=0;void addedge(int from,int to,int v,int id){ edge[h].to=to;edge[h].v=v;edge[h].id=id;edge[h].pre=head[from]; head[from]=h;}void addq(int from,int to,int v,int id){ q[h].to=to;q[h].v=v;q[h].id=id;q[h].pre=hq[from]; hq[from]=h;}void dfs(int u,int val){ d[u]=val; for(int i=head[u];i>-1;i=edge[i].pre) { int v=edge[i].to; if(!vis[v]) { vis[v]=1; dfs(v,val+edge[i].v); } }}int getf(int k){ if(k==f[k]) return k; else return f[k]=getf(f[k]);}void uin(int a,int b){ int x=getf(a),y=getf(b); if(x!=y) f[y]=x;}void Tarjan(int u){ for(int i=head[u];i>-1;i=edge[i].pre) { node e=edge[i]; if(!vis[e.to]) { vis[e.to]=1; Tarjan(e.to); uin(u,e.to); } } col[u]=1; for(int i=hq[u];i>-1;i=q[i].pre) { node e=q[i]; if(!col[e.to]) continue; ans[e.id]=d[u]+d[e.to]-2*d[f[getf(e.to)]];//不能直接f[e.to],因为这里确保是最上面的祖先,因为uin的时候f[y]=x,但是以y为爸爸的孩子们的爸爸还没有改到x~ }}int main(){ int T; scanf("%d",&T); while(T--) { int n,m; h=0; scanf("%d %d",&n,&m); init(n); for(int i=0;i<n-1;i++) { int a,b,k; scanf("%d %d %d",&a,&b,&k); addedge(a,b,k,i);h++;addedge(b,a,k,i);h++; } vis[1]=1; dfs(1,0);h=0; for(int i=1;i<=m;i++) { int a,b; scanf("%d %d",&a,&b); addq(a,b,0,i);h++;addq(b,a,0,i);h++; } memset(vis,0,sizeof(vis));vis[1]=1; Tarjan(1); for(int i=1;i<=m;i++) { printf("%I64d\n",ans[i]); } // printf("\n"); } return 0;}
阅读全文
0 0
- HDU How far away ?
- How far away ? HDU
- How far away ? HDU
- How far away ? HDU
- How far away ? HDU
- HDU 2586 How far away ?
- HDU 2586 How far away?
- hdu 2586 How far away ?
- HDU 2586 How far away ?
- hdu 2586 How far away ?
- HDU 2586 How far away ?
- hdu 2586 How far away?
- hdu 2586 how far away?
- How far away hdu 2586
- hdu 2586 How far away
- HDU-2586-How far away ?
- HDU 2586 How far away ?
- hdu 2586 How far away ?
- 把python基本功搞扎实(1)
- week5-leetcode #8-String to Integer (atoi)[Medium]
- ios扩展
- C语言交换两个变量的值
- 破解centos系统root密码
- How far away ? HDU
- 方格填数【相邻两数互质】-DFS深度优先搜索
- 会话 session
- Matlab的GUI编程入门项目一:常用三角函数的绘制
- python 求和为正整数n的连续整数序列
- 单词的长度
- tp3控制器对应的视图的命名方式
- APM_PX4学习笔记(1):Make 编译
- Python引用2(Django系列3)