[NOIP2013][CODEVS3287]货车运输(kruskal+树上倍增)
2016-04-02 18:47
513 查看
题目描述
传送门题解
很久之前写的,发现没有发题解,于是来写一发。用kruskal求最大生成树,然后倍增。
现在看当时的码风都非常的naive~
还有发现自己用了poj当做变量名= =吓哭了T_T
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define MAXN 50005 #define sz 13 #define maxn 10005 #define large 2100000000 using namespace std; int n,m,sum,r,tot,x,y,p; int father[maxn],ccount[maxn],root[maxn],point[maxn],next[2*MAXN],v[2*MAXN],c[2*MAXN],h[maxn],mi[sz],f[maxn][sz],s[maxn][sz]; struct hp{ int left,right,delta; }a[MAXN]; int cmp(hp a,hp b){ return a.delta>b.delta; } int find(int x){ if (x==father[x]) return x; father[x]=find(father[x]); return father[x]; } void merge(int x,int y){ int f1=find(x); int f2=find(y); father[f1]=f2; } inline void add(int x,int y,int z,int i){ v[i]=y; c[i]=z; next[i]=point[x]; point[x]=i; } inline void build(int x,int fa,int dep){ h[x]=dep; for (int i=1;i<sz;++i){ if (h[x]-mi[i]<1) break; f[x][i]=f[f[x][i-1]][i-1]; s[x][i]=min(s[x][i-1],s[f[x][i-1]][i-1]); } for (int i=point[x];i;i=next[i]) if (v[i]!=fa){ f[v[i]][0]=x; s[v[i]][0]=c[i]; build(v[i],x,dep+1); } } inline int lca(int x,int y){ int Min=large; if (h[x]<h[y]) swap(x,y); int k=h[x]-h[y]; for (int i=0;i<sz;++i) if ((k>>i)&1){ Min=min(Min,s[x][i]); x=f[x][i]; } if (x==y) return Min; for (int i=sz-1;i>=0;--i) if (f[x][i]!=f[y][i]){ Min=min(Min,min(s[x][i],s[y][i])); x=f[x][i]; y=f[y][i]; } Min=min(Min,min(s[x][0],s[y][0])); return Min; } int main(){ scanf("%d%d",&n,&m); mi[0]=1; for (int i=1;i<sz;++i) mi[i]=mi[i-1]*2; for (int i=1;i<=n;++i) father[i]=i; for (int i=1;i<=m;++i){ scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].delta); if (find(a[i].left)!=find(a[i].right)) merge(a[i].left,a[i].right); } for (int i=1;i<=n;++i) int poj=find(i); for (int i=1;i<=n;++i) ++ccount[father[i]]; for (int i=1;i<=n;++i) if (ccount[i]){ sum+=ccount[i]-1; root[++r]=i; } sort(a+1,a+m+1,cmp); for (int i=1;i<=n;++i) father[i]=i; int i=0; while(tot<sum){ i++; if (find(a[i].left)!=find(a[i].right)){ add(a[i].left,a[i].right,a[i].delta,(++tot)<<1); add(a[i].right,a[i].left,a[i].delta,tot<<1|1); merge(a[i].left,a[i].right); } } memset(s,127/3,sizeof(s)); for (int i=1;i<=r;++i){ int tmp=root[i]; build(tmp,0,1); } scanf("%d",&p); for (int i=1;i<=p;++i){ scanf("%d%d",&x,&y); if (find(x)!=find(y)){ printf("-1\n");continue; } int ans=lca(x,y);printf("%d\n",ans); } }
相关文章推荐
- Java并发编程系列之八:wait()、notify()和notifyAll()
- 第九章 原型模式
- 可视化深度学习和人类感知Visualizing Representations: Deep Learning and Human Beings-1
- Spring学习---1
- URL链接中汉字乱码转UTF-8和gb2312
- 一步一步利用django创建博客应用(二)
- zoj2876——May Day Holiday(算星期)
- Java内存区域划分
- ubuntu下安装编译链
- 快速排序
- Micro2440数据传输---串口通信
- ROS基础环境的配置
- select标签中显示指定内容
- shell 脚本执行日志通用模块
- 《古文字学》学习
- Android开发:解决android:gravity不能居中问题
- UFLDL Tutorial 笔记
- Android开发中的一个小功能 清空搜索框的文字
- maven 镜像使用
- 希尔排序