noip2013truck树上路径倍增
2015-11-07 22:45
218 查看
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; #define INF 0x7fffffff int n,m,x,y,z,l,s,u,v,q; bool vis[10010]; struct point{ int x,y,z; }a[50010]; struct node{ int y,z,next; }edge[500010]; int father[50010],deep[50010],head[50010]; int f[50010][20],g[50010][20]; int cmp(point a,point b) { return a.z>b.z; } int find(int x) { if (father[x]!=x) father[x]=find(father[x]); return father[x]; } void add(int x,int y,int z) { l++; edge[l].y=y;edge[l].z=z; edge[l].next=head[x]; head[x]=l; } void dfs(int x) { vis[x]=1; for (int i=head[x];i!=0;i=edge[i].next) { if (vis[edge[i].y]==0) { deep[edge[i].y]=deep[x]+1; f[edge[i].y][0]=x; g[edge[i].y][0]=edge[i].z; dfs(edge[i].y); } } } void dp() { for (int j=1;j<=15;j++) for (int i=1;i<=n;i++) { f[i][j]=f[f[i][j-1]][j-1]; g[i][j]=min(g[i][j-1],g[f[i][j-1]][j-1]); } } int lca(int x,int y) { int t,ans=INF; if (find(x)!=find(y)) return -1; if (deep[x]>deep[y]) { t=x;x=y;y=t; } for (int i=15;i>=0;i--) if (deep[f[y][i]]>=deep[x]) { ans=min(ans,g[y][i]); y=f[y][i]; } if (x==y) return ans; for (int i=15;i>=0;i--)//这里算到0!!,因为跳到的地方是父节点不相同的地方,最后在往上跳一个 if (f[x][i]!=f[y][i]) { ans=min(ans,g[x][i]); ans=min(ans,g[y][i]); x=f[x][i]; y=f[y][i]; } ans=min(ans,g[x][0]); ans=min(ans,g[y][0]); return ans; } int main() { freopen("truck.in","r",stdin); freopen("truck.out","w",stdout); scanf("%d%d", &n, &m); for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x, &a[i].y, &a[i].z); sort(a+1,a+m+1,cmp); for (int i=1;i<=n;i++) father[i]=i; s=0; memset(head,0,sizeof(head)); for (int i=1;i<=m;i++) { u=find(a[i].x); v=find(a[i].y); if (u!=v) { s++; father[u]=father[v]; add(a[i].x,a[i].y,a[i].z); add(a[i].y,a[i].x,a[i].z); } if (s==n-1) break; } memset(vis,0,sizeof(vis)); memset(f,0,sizeof(f)); memset(g,0x3f,sizeof(g)); for (int i=1;i<=n;i++) { if (!vis[i]) { deep[i]=1; dfs(i); } } dp(); scanf("%d", &q); while (q--) { scanf("%d%d", &x, &y); printf("%d\n", lca(x,y)); } fclose(stdin); fclose(stdout); return 0; }
相关文章推荐
- 侧拉中的”搜索“
- f2fs解析(八)node 管理器中的node_info
- 迭代器删除元素
- manifest竟然不报错
- 小游戏
- c++rand()与srand()的使用
- 周爱民:真正的架构师是没有title的(图灵访谈)
- python之函数用法islower()
- Android中自定义控件获取text的宽高方式
- 插件问题
- hdoj 3766 Knight's Trip 【】
- 字符串-查找第一个只出现一次的字符
- B - 四月纲领 light oj 1245【数论】
- leetcode-Remove Linked List Elements
- 2,XCode的快捷键
- 【Oracle】无宕机迁移更换asm磁盘
- JavaScript高级程序设计之DOM2和DOM3之样式之访问元素的样式第12.2.1讲
- 剑指offer之65 滑动窗口的最大值问题
- Andrid的网络开发技术
- 3.0MongoDB对一个collection的常用操作