LCA,有向图求两点间距离,无向图求两点间距离,倍增
2018-01-20 19:54
344 查看
LCA就是求公共祖先。优质博客推荐
但是不推荐它的伪代码,感觉思路没错,但是有点问题。
我随手写了一个,有错欢迎之处
vis[u]为什么放哪个地方而不放在f[v]=u前面,因为那样遍历不到根节点。
无向图可以放在位置1和位置2,讲道理,位置1更快。
但是有向图只能放在位置2,否则提前标记自己,但是自己不一定是祖先,因为自己是有向图。
那么公共祖先有什么用呢?
裸题有用,但是大部分都不是,我学了一个求两点间距离,有意思的很。
首先说一下无向图,只需在dfs的时候传递一个deep变量一直逐层加就好了。
然后dis[u]=deep,那么就两点间距离就是dis[u]+dis[v]-2*dis[get(v)]。
那么有向图必需从根节点dfs,无向图可以从任意节点。
hdu6115
但是不推荐它的伪代码,感觉思路没错,但是有点问题。
我随手写了一个,有错欢迎之处
int get(int u) { if(f[u]==u) return u; else f[u]=get(f[u]); } void dfs(int u,int pre) { //vis[u]=1;//位置1 for(int i=first[u];i!=-1;i=e[i].nex) { int v=e[i].v; if(pre==v) continue; if(!vis[v]) { dfs(v,u); f[v]=u; } } vis[u]=1;//位置2 for(int i=first2[u];i!=-1;i=e2[i].nex) { int v=e2[i].v; int id=e2[i].id; if(!vis[v]) { ans[id]=get(v); } } }
vis[u]为什么放哪个地方而不放在f[v]=u前面,因为那样遍历不到根节点。
无向图可以放在位置1和位置2,讲道理,位置1更快。
但是有向图只能放在位置2,否则提前标记自己,但是自己不一定是祖先,因为自己是有向图。
那么公共祖先有什么用呢?
裸题有用,但是大部分都不是,我学了一个求两点间距离,有意思的很。
首先说一下无向图,只需在dfs的时候传递一个deep变量一直逐层加就好了。
然后dis[u]=deep,那么就两点间距离就是dis[u]+dis[v]-2*dis[get(v)]。
那么有向图必需从根节点dfs,无向图可以从任意节点。
无向图求两点距离
hdu2874#include<stdio.h> #include<string.h> #include<string> #include<iostream> #include<algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define LL long long using namespace std; const int maxn=20005; const int maxm=2000005; int n,m,c; struct node { int v,w,nex; } e[maxn]; struct node2 { int id,v,nex; } e2[maxm]; int first[maxn/2]; int first2[maxn/2]; int tot,tot2; int vis[maxn]; int f[maxn]; int dis[maxn]; int ans[maxm/2]; void edge(int u,int v,int w) { e[tot].v=v; e[tot].w=w; e[tot].nex=first[u]; first[u]=tot++; } void edge2(int id,int u,int v) { e2[tot2].id=id; e2[tot2].v=v; e2[tot2].nex=first2[u]; first2[u]=tot2++; } void init() { mem(first,-1); mem(first2,-1); tot=0; tot2=0; mem(vis,0); for(int i=1; i<=n; i++) { f[i]=i; } mem(dis,0); mem(ans,-1); } int get(int u) { if(f[u]==u) { return u; } else { return f[u]=get(f[u]); } } //void marge(int u,int v) //{ // int f1=get(u); // int f2=get(v); // if(f1!=f2) // f[f2]=f1; //} int dfs(int u,int pre,int deep,int root) { vis[u]=root; dis[u]=deep; int v; for(int i=first[u]; i!=-1; i=e[i].nex) { v=e[i].v; if(v==pre) continue; //printf("%d %d\n",u,v); if(!vis[v]) { //printf(" %d\n",v); dfs(v,u,deep+e[i].w,root); f[v]=u; } } for(int i=first2[u]; i!=-1; i=e2[i].nex) { v=e2[i].v; if(vis[v]==root) { //printf(" %d %d %d\n",dis[u],dis[v],get(v)); ans[e2[i].id]=dis[u]+dis[v]-2*dis[get(v)]; } } } void LCA() { for(int i=1; i<=n; i++) { //printf("i=%d\n",i); if(!vis[i]) { //printf("i=%d\n",i); dfs(i,-1,0,i); } } } int main() { while(~scanf("%d%d%d",&n,&m,&c)) { init(); for(int i=0; i<m; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); edge(u,v,w); edge(v,u,w); } for(int i=1; i<=c; i++) { int u,v; scanf("%d%d",&u,&v); edge2(i,u,v); edge2(i,v,u); } LCA(); for(int i=1; i<=c; i++) { if(ans[i]!=-1) printf("%d\n",ans[i]); else printf("Not connected\n"); } } return 0; }
有向图两点间距离
hdu2586#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<map> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) const int maxn=40010; int n,m; int vis[maxn]; int f[maxn]; //int pre[maxn]; int ans[maxn]; int dis[maxn]; map<string,int>str; int top; int tot,tot2; struct node { int u,v,w,nex; } e[maxn*10]; int first[maxn]; struct node2 { int id; int u,v,nex; } e2[maxn*10]; int first2[maxn]; void edge(int u,int v,int w) { e[tot].v=v; e[tot].w=w; e[tot].nex=first[u]; first[u]=tot++; } void edge2(int id,int u,int v) { e2[tot2].id=id; e2[tot2].u=u; e2[tot2].v=v; e2[tot2].nex=first2[u]; first2[u]=tot2++; } void init() { tot=tot2=0; mem(first,-1); mem(first2,-1); mem(vis,0); for(int i=0; i<=n; i++) { f[i]=i; } mem(ans,0); top=0; //mem(pre,-1); } int get(int u) { if(f[u]==u) return u; else return f[u]=get(f[u]); } void dfs(int u,int deep,int pre) { vis[u]=1; dis[u]=deep; for(int i=first[u]; i!=-1; i=e[i].nex) { int v=e[i].v; if(pre==v) continue; if(!vis[v]) { dfs(v,deep+e[i].w,u); f[v]=u; } } for(int i=first2[u]; i!=-1; i=e2[i].nex) { int v=e2[i].v; int id=e2[i].id; if(vis[v]) { ans[id]=dis[u]+dis[v]-2*dis[get(v)]; } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); int u,v,w; for(int i=1; i<n; i++) { scanf("%d%d%d",&u,&v,&w); edge(u,v,w); edge(v,u,w); } for(int i=1; i<=m; i++) { scanf("%d%d",&u,&v); edge2(i,u,v); edge2(i,v,u); } dfs(1,0,-1); for(int i=1; i<=m; i++) { printf("%d\n",ans[i]); } } return 0; }
LCA倍增
优质博客推荐hdu6115
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<map> #include<vector> using namespace std; const int inf=0x3f3f3f3f; #define mem(a,b) memset(a,b,sizeof(a)) const int maxn=100005; int n,m; int vis[maxn]; int deep[maxn]; int dis[maxn];//记录深度,根为0,第一层为1,递推。。。 int p[maxn][25];//第i个点往上2^j个祖先 vector<int>v1[maxn]; int tot; struct node { int u,v,w,nex; } e[maxn*10]; int first[maxn]; void edge(int u,int v,int w) { e[tot].v=v; e[tot].w=w; e[tot].nex=first[u]; first[u]=tot++; } void init() { tot=0; mem(first,-1); mem(vis,0); mem(dis,0); mem(deep,0); mem(p,0); for(int i=0; i<=n; i++) v1[i].clear(); } void dfs(int u,int d,int pre) { vis[u]=1; dis[u]=d; for(int i=1; i<=22; i++) { p[u][i]=p[p[u][i-1]][i-1]; } for(int i=first[u]; i!=-1; i=e[i].nex) { int v=e[i].v; if(pre==v) continue; if(!vis[v]) { deep[v]=deep[u]+1; p[v][0]=u; dfs(v,d+e[i].w,u); } } } int LCA(int a,int b)//返回a和b的公共祖先 { if(dis[a]>dis[b]) swap(a,b);//保证a在b点的上方 for(int i=20; i>=0; i--) if(dis[a]<=dis[b]-(1<<i)) b=p[b][i]; //把b移到和a同一个深度 if(a==b) return a; for(int i=20; i>=0; i--) { if(p[a][i]==p c70e [b][i]) continue; else a=p[a][i],b=p[b][i];//一起向上跳跃 } return p[a][0]; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); int u,v,w; for(int i=1; i<n; i++) { scanf("%d%d%d",&u,&v,&w); edge(u,v,w); edge(v,u,w); } for(int i=1; i<=m; i++) { int p; scanf("%d",&p); for(int j=1; j<=p; j++) { int aa; scanf("%d",&aa); v1[i].push_back(aa); } } dfs(1,0,-1); int q; scanf("%d",&q); for(int i=1; i<=q; i++) { int minn=inf; scanf("%d%d",&u,&v); for(int j=0; j<v1[u].size(); j++) { for(int k=0; k<v1[v].size(); k++) { int uu=v1[u][j]; int vv=v1[v][k]; int gg=LCA(uu,vv); //printf("gg=%d\n",gg); minn=min(minn,dis[uu]+dis[vv]-2*dis[gg]); } } printf("%d\n",minn); } } return 0; }
相关文章推荐
- hdu 2586 How far away ?(LCA 求两点距离)
- POJ 1986 Distance Queries LCA树上两点的距离
- poj 2763 Housewife Wind 【LCA 转RMQ】 【查询两点间最短距离 + 边权更新】
- poj 1986 Distance Queries 【LCA转RMQ 裸题】【求两点最短距离】
- UESTC(LCA应用:求两点之间的距离)
- POJ 2874 LCA 树上任意两点距离
- POJ 1986 Distance Queries(查询两点距离,LCA)
- HDU2874(LCA应用:求两点之间距离,图不连通)
- HDU2586(LCA应用:在带权树中求任意两点之间的距离)
- POJ 1986 Distance Queries LCA两点距离树
- poj 1986 Distance Queries(LCA求两点距离模版)
- Poj 1986 Distance Queries (LCA 树上两点间最短距离)
- LCA+RMQ求树中两点距离
- 根据经纬度计算两点之间的距离的公式推导过程以及google.maps的测距函数
- python利用地图两个点的经纬度计算两点间距离
- 已知两点的经纬度,求某点到该两点的连线的最短距离
- 在线倍增算法求LCA
- poj1330 倍增LCA
- YTU 2619: B 友元类-计算两点间距离
- IOS开发——根据两点的经纬度计算距离