bzoj 1602 [Usaco2008 Oct]牧场行走(LCA模板)
来源:互联网 发布:知乎登录页面 编辑:程序博客网 时间:2024/06/05 08:54
1602: [Usaco2008 Oct]牧场行走
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 379 Solved: 216
[Submit][Status][Discuss]
Description
N头牛(2<=n<=1000)别人被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头牛在第i块牧场吃草。这n块土地被n-1条边连接。奶牛可以在边上行走,第i条边连接第Ai,Bi块牧场,第i条边的长度是Li(1<=Li<=10000)。这些边被安排成任意两头奶牛都可以通过这些边到达的情况,所以说这是一棵树。这些奶牛是非常喜欢交际的,经常会去互相访问,他们想让你去帮助他们计算Q(1<=q<=1000)对奶牛之间的距离。
Input
*第一行:两个被空格隔开的整数:N和Q*第二行到第n行:第i+1行有两个被空格隔开的整数:AI,BI,LI*第n+1行到n+Q行:每一行有两个空格隔开的整数:P1,P2,表示两头奶牛的编号。
Output
*第1行到第Q行:每行输出一个数,表示那两头奶牛之间的距离。
Sample Input
4 2
2 1 2
4 3 2
1 4 3
1 2
3 2
2 1 2
4 3 2
1 4 3
1 2
3 2
Sample Output
2
7
7
HINT
Source
资格赛
【代码】
//O(qlogn)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<vector> 5 #include<iostream> 6 #define FOR(a,b,c) for(int a=(b);a<(c);a++) 7 using namespace std; 8 9 const int maxn = 100000+10;10 const int maxd = 22;11 12 struct Edge{ int u,v,w;13 };14 vector<int> G[maxn];15 vector<Edge> es;16 17 int d[maxn],dist[maxn];18 int p[maxn][maxd],pd[maxn][maxd];19 20 void addedge(int u,int v,int w) {21 es.push_back((Edge){u,v,w});22 int m=es.size(); G[u].push_back(m-1);23 }24 void dfs(int u,int fa) { //构造dist 25 for(int i=0;i<G[u].size();i++) {26 Edge e=es[G[u][i]];27 int v=e.v;28 if(v!=fa) {29 d[v]=d[u]+1; dist[v]=dist[u]+e.w;30 p[v][0]=u , pd[v][0]=e.w;31 dfs(v,u);32 }33 }34 }35 int query(int u,int v) { //查询 36 if(d[v]>d[u]) swap(u,v);37 for(int i=maxd-1;i>=0;i--)38 if(d[p[u][i]]>=d[v]) u=p[u][i]; //调整至同意高度 39 if(u==v) return u; //同一子树则返回 40 for(int i=maxd-1;i>=0;i--)41 if(p[u][i]!=p[v][i])42 u=p[u][i] , v=p[v][i]; //查找lca 43 return p[u][0];44 }45 46 int n,q;47 48 void read(int& x) {49 char c=getchar(); 50 while(!isdigit(c)) c=getchar();51 x=0;52 while(isdigit(c))53 x=x*10+c-'0' , c=getchar();54 }55 int main() {56 read(n),read(q);57 int u,v,w;58 for(int i=1;i<n;i++) {59 read(u),read(v),read(w);60 addedge(u,v,w) , addedge(v,u,w);61 }62 dfs(1,-1);63 for(int k=1;k<maxd;k++) for(int i=1;i<=n;i++) { //构造倍增数组 64 p[i][k]=p[p[i][k-1]][k-1];65 pd[i][k]=pd[i][k-1]+pd[p[i][k-1]][k-1];66 }67 while(q--) {68 read(u),read(v);69 printf("%d\n",dist[u]+dist[v]-2*dist[query(u,v)]);70 }71 return 0;72 }
//O(n+q)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<vector> 5 #include<iostream> 6 using namespace std; 7 8 const int maxn = 100000+10; 9 const int maxq = 100000+10;10 11 struct Edge{ int u,v,w;12 };13 struct node { int v,i; };14 vector<int> G[maxn];15 vector<Edge> es;16 vector<node> que[maxn];17 int U[maxq],V[maxq];18 19 void addedge(int u,int v,int w) {20 es.push_back((Edge){u,v,w});21 int m=es.size(); G[u].push_back(m-1);22 }23 int p[maxn];24 int find(int u) { return u==p[u]? u:p[u]=find(p[u]);25 }26 27 int dist[maxn];28 void dfs(int u,int fa) { //求dist 29 for(int i=0;i<G[u].size();i++) {30 Edge e=es[G[u][i]]; int v=e.v;31 if(v!=fa) dist[v]=dist[u]+e.w , dfs(v,u);32 }33 }34 int vis[maxn],lca[maxq];35 void tarjan(int u,int fa) { 36 p[u]=u;37 for(int i=0;i<G[u].size();i++) {38 Edge e=es[G[u][i]]; int v=e.v;39 if(v!=fa) tarjan(v,u),p[v]=u; //递归处理 合并集合 40 }41 vis[u]=1;42 for(int i=0;i<que[u].size();i++) { //求与u相关的询问 43 int v=que[u][i].v;44 if(vis[v]) lca[que[u][i].i]=find(v); 45 //如果已经被访问 lca为v集合的代表元x //若v是u子则x=u 若非子则因u还未访问完集合并未向上合并所以代表元为lca 46 }47 }48 49 int n,q;50 void read(int& x) {51 char c=getchar(); 52 while(!isdigit(c)) c=getchar();53 x=0;54 while(isdigit(c))55 x=x*10+c-'0' , c=getchar();56 }57 58 int main() {59 read(n),read(q);60 int u,v,w;61 for(int i=1;i<n;i++) {62 read(u),read(v),read(w);63 addedge(u,v,w) , addedge(v,u,w);64 }65 for(int i=0;i<q;i++) {66 read(u),read(v);67 U[i]=u , V[i]=v;68 que[u].push_back((node){v,i});69 que[v].push_back((node){u,i});70 }71 tarjan(n>>1,-1) , dfs(n>>1,-1);72 for(int i=0;i<q;i++) {73 u=U[i] , v=V[i];74 int lc=lca[i];75 printf("%d\n",dist[u]+dist[v]-(dist[lc]<<1));76 }77 return 0;78 }
LCA的一种比较快的写法
////////////////////////////////////////////////////int siz[N],top[N],son[N],fa[N];void dfs1(int u) {siz[u]=1,son[0]=0; dfn[u]=++dfsc;for(int i=0;i<g[u].size();i++) {int v=g[u][i];if(v!=fa[u]) {fa[v]=u; d[v]=d[u]+1;dfs1(v);siz[u]+=siz[v];if(siz[v]>siz[son[u]]) son[u]=v;}}}void dfs2(int u,int tp) {top[u]=tp;if(son[u]) dfs2(son[u],tp);for(int i=0;i<g[u].size();i++) {int v=g[u][i];if(v!=son[u] && v!=fa[u]) dfs2(v,v);}}int LCA(int u,int v) {while(top[u]!=top[v])if(d[top[u]]>=d[top[v]]) u=fa[top[u]];else v=fa[top[v]];return d[u]<d[v]? u:v;}////////////////////////////////////////////////
题目部分戳这:http://www.cnblogs.com/lidaxin/p/5115660.html
0 0
- bzoj 1602 [Usaco2008 Oct]牧场行走(LCA模板)
- bzoj 1602: [Usaco2008 Oct]牧场行走(暴力LCA)
- BZOJ 1602 Usaco2008 Oct 牧场行走 倍增LCA
- 1602: [Usaco2008 Oct]牧场行走|Lca
- [BZOJ1602][Usaco2008 Oct]牧场行走(LCA)
- BZOJ 1602: [Usaco2008 Oct]牧场行走
- BZOJ 1602 [Usaco2008 Oct]牧场行走 dfs
- BZOJ 1602: [Usaco2008 Oct]牧场行走
- BFS-BZOJ-1602-[Usaco2008 Oct]牧场行走
- bzoj 1602: [Usaco2008 Oct]牧场行走
- BZOJ 1602 [Usaco2008 Oct]牧场行走
- [BZOJ]1602: [Usaco2008 Oct]牧场行走
- 【bzoj 1602】[Usaco2008 Oct]牧场行走
- BZOJ [Usaco2008 Oct]牧场行走
- bzoj1602[Usaco2008 Oct]牧场行走(lca模版)
- [Usaco2008 Oct]牧场行走
- *【bzoj 1602】牧场行走(LCA)
- [Bzoj1602][Usaco2008 Oct]牧场行走
- bzoj 1449 [JSOI2009]球队收益(费用拆分,最小费用流)
- vijos1891 学姐的逛街计划(线性规划)
- bzoj 2324 [ZJOI2011]营救皮卡丘(floyd,费用流)
- UVA 11478 Halum(差分约束)
- bzoj 2330 [SCOI2011]糖果(差分约束系统)
- bzoj 1602 [Usaco2008 Oct]牧场行走(LCA模板)
- bzoj 1787 [Ahoi2008]Meet 紧急集合(1832 [AHOI2008]聚会)
- 1025. 反转链表
- bzoj 1089 [SCOI2003]严格n元树(DP+高精度)
- 浅谈《微信抢红包原理》
- 国家集训队论文【index】
- bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)
- bzoj 1055 [HAOI2008]玩具取名(区间DP)
- bzoj 1560 [JSOI2009]火星藏宝图(DP)