【LCA转RMQ求树上任意两点最短路】HDU 2874
2012-02-08 15:17
477 查看
这里有可能不连通,可以通过添加一个虚根把森林变成树,最后如果LCA(u,v) = 0就表示不连通
个人比较喜欢用离线算法,tarjan还需要掌握
个人比较喜欢用离线算法,tarjan还需要掌握
#define N 10010 struct edge{ int v; int len; int next; }e[2*N]; int ecnt; int head ; bool vis ; int n;//点数 int R ;//第一次出现i点下标 int p[N*2];//记录路径点编号 int dis ;//与根的距离 int dep[2*N];//深度 int dp[20][2*N];//从j开始长度为2^i路径的最近公共祖先下标,这里这里!!!第二维要2倍大小!! int num; int fa ; void init(){ memset(head,-1,sizeof(head)); memset(R,-1,sizeof(R)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++)fa[i] = i; ecnt=0; } void add(int u,int v,int len){ e[ecnt].v = v; e[ecnt].len = len; e[ecnt].next = head[u]; head[u] = ecnt++; e[ecnt].v = u; e[ecnt].len = len; e[ecnt].next = head[v]; head[v] = ecnt++; } int find(int x){ if(fa[x] != x) fa[x] = find(fa[x]); return fa[x]; } void uni(int u,int v){ int a = find(u); int b = find(v); if(a == b)return ; fa[a] = b; } void dfs(int u,int depth){ vis[u] = 1; p[++num] = u; dep[num] = depth; for(int i=head[u];i!=-1;i=e[i].next){ int v = e[i].v; if(!vis[v]){ dis[v] = dis[u]+e[i].len; dfs(v,depth+1); p[++num] = u; dep[num] = depth; } } } void init_rmq(){ int i,j; for(i=1;i<=num;i++){ if(R[p[i]] == -1){ R[p[i]] = i; } } for(i=1;i<=num;i++){ dp[0][i] = i; } int t = (int)(log(num*1.0)/log(2.0)); for(i=1;i<=t;i++){ for(j=1;j+(1<<(i-1))<=num;j++){ int a = dp[i-1][j],b = dp[i-1][j+(1<<(i-1))]; if(dep[a]<=dep[b]){ dp[i][j] = a; } else dp[i][j] = b; } } } int rmq(int u,int v){//返回最近公共祖先的编号 if(R[u]>=R[v])swap(u,v); int s = R[u],t = R[v]; int k = (int)(log((t-s+1)*1.0)/log(2.0)); int a = dp[k][s],b = dp[k][t-(1<<k)+1]; if(dep[a]<=dep[b])return p[a]; else return p[b]; } int main(){ int m,c; while(scanf("%d%d%d",&n,&m,&c) != -1){ int i,j; init(); int x,y,z; while(m--){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); uni(x,y); } for(i=1;i<=n;i++){ if(fa[i] == i){ add(i,0,0);//添加虚根0把森林变成树 } } num = 0; dis[0] = dep[0] = 0; dfs(0,0); init_rmq(); while(c--){ scanf("%d%d",&x,&y); int f = rmq(x,y); if(!f)puts("Not connected"); else printf("%d\n",dis[x]+dis[y]-2*dis[f]); } } return 0; }
相关文章推荐
- POJ 2874 LCA 树上任意两点距离
- Connections between cities HDU - 2874(LCA)(RMQ)(dfs)(st算法)
- HDU 2874 Connections between cities(LCA + RMQ)
- hdu 2376(求树上任意两点之间距离之和的平均值)
- hdu 2874 Connections between cities(st&rmq LCA)
- hdu 2874 Connections between cities (LCA转RMQ)
- HDU 5723 Abandoned country (并查集 + DFS+求解树上任意两点间的距离的平均值)
- hdu 4460 求所有任意两点间的最短路
- hdu 2874 Connections between cities [LCA] (lca->rmq)
- HDU 2874 LCA转RMQ裸题
- HDU 4460 Friend Chains(任意两点最短路的最大值 bfs或spfa)
- HDU 2376 树形dp|树上任意两点距离和的平均值
- 【LCA转RMQ ST】 HDU 2874 Connections between cities
- 【LCA转RMQ ST】 HDU 2874 Connections between cities
- hdu 2376 Average distance DFS 求树上任意两点距离和
- hdu 2376(求树上任意两点之间距离之和的平均值)
- HDU2874——Connections between cities 详解 (LCA,RMQ,数据结构,dfs序,并查集)
- HDU 2874 Connections between cities (LCA)
- hdu 2874 Connections between cities(LCA离线算法)
- (HDU 5723)Abandoned country <最小生成树 + 树上所有两点之间的距离的期望> 多校训练1