【边分治】Kuala Lumpur 2008
来源:互联网 发布:袁隆平杂交水稻数据 编辑:程序博客网 时间:2024/05/20 16:41
求树上路径第一维之和小于m,第二维之和最大
拆边,每个点的儿子用加点的方式左儿子右兄弟的表示,这样就是一棵二叉树了
虽然数组和bfs很多,但是写得很顺...
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>const int maxn=200000,maxm=500000,oo=1073741819;using namespace std;struct sta{ int rt,d,l;}A[maxn];int tail[maxn],next[maxm],sora[maxm],id[maxm];int l[maxm],r[maxm],D[maxm],L[maxm],fl[maxm],n,ss,tot,w_time;int v[maxn],T[maxn],u[2][maxn],st[maxn],sd[maxn],sl[maxn];int size[maxn],rt[maxn],ry[maxn],last[maxn];int ans,M,t;void origin(){ tot=0; ss=n+n; for (int i=1;i<=ss;i++) tail[i]=i,next[i]=0;}void link(int x,int y,int d,int ll){ ++tot; ++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0,id[ss]=tot; ++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x,next[ss]=0,id[ss]=tot; l[tot]=x,r[tot]=y,D[tot]=d,L[tot]=ll;}void bfs1(){ int h,r,ne,na; for (int i=1;i<=n;i++) v[i]=0; h=r=0; st[r=1]=1,v[1]=1; for (;h<r;) { ne=st[++h]; for (int i=ne;next[i];) { i=next[i],na=sora[i]; if (!v[na]) { st[++r]=na; A[na].rt=ne,A[na].d=D[id[i]],A[na].l=L[id[i]]; v[na]=1; } } }// cout<<r<<endl; origin(); for (int i=1;i<=n;i++) last[i]=0; int cnt=n; for (int i=r;i>=2;i--) { ne=st[i]; na=A[ne].rt; if (!last[na]) { last[na]=++cnt; link(na,last[na],0,0); } else { ++cnt; link(last[na],cnt,0,0); last[na]=cnt; } link(last[na],ne,A[ne].d,A[ne].l); } n=cnt;}int bfs2(int s){ int h,r,ne,na; ++w_time; h=r=0; st[r=1]=s,T[s]=w_time,size[s]=0; for (;h<r;) { ne=st[++h]; for (int i=ne;next[i];) { i=next[i],na=sora[i]; if (T[na]!=w_time && fl[id[i]]) { T[na]=w_time,size[na]=0,rt[na]=ne,ry[na]=id[i]; st[++r]=na; } } } int Mins=oo,Mini=0; for (int i=r;i>=2;i--) { ne=st[i]; size[ne]++; int tmp=max(size[ne],r-size[ne]); if (tmp<Mins) { Mins=tmp,Mini=ry[ne]; } size[rt[ne]]+=size[ne]; } return Mini;}int bfs3(int s){ int h,r,ne,na; ++w_time; h=r=0; st[r=1]=s,T[s]=w_time,sd[s]=0,sl[s]=0; for (;h<r;) { ne=st[++h]; for (int i=ne;next[i];) { i=next[i],na=sora[i]; if (T[na]!=w_time && fl[id[i]]) { T[na]=w_time,sd[na]=sd[ne]+D[id[i]],sl[na]=sl[ne]+L[id[i]]; st[++r]=na; } } } return r;}bool cmp1(int i,int j){ return sd[i]>sd[j];}bool cmp2(int i,int j){ return sd[i]<sd[j];}void calc(int s){ int G=bfs2(s); if (!G) return ; fl[G]=0; int h[2]; h[0]=bfs3(l[G]); for (int i=1;i<=h[0];i++) u[0][i]=st[i]; h[1]=bfs3(r[G]); for (int i=1;i<=h[1];i++) u[1][i]=st[i]; sort(u[0]+1,u[0]+h[0]+1,cmp1); sort(u[1]+1,u[1]+h[1]+1,cmp2); for (int i=1,j=1,Max=-oo;i<=h[0];i++) { for (;(j<=h[1]) && (sd[u[0][i]]+sd[u[1][j]]+D[G]<=M);++j) Max=max(Max,sl[u[1][j]]); int tmp=sl[u[0][i]]+Max+L[G]; ans=max(ans,tmp); } calc(l[G]); calc(r[G]);}int main(){ scanf("%d",&t); for (int test=1;t;t--,test++) { printf("Case %d: ",test); scanf("%d%d",&n,&M); origin(); for (int i=1;i<=n-1;i++) { int x,y,d,l; scanf("%d%d%d%d",&x,&y,&d,&l); link(x,y,d,l); } bfs1(); for (int i=1;i<=tot;i++) fl[i]=1; for (int i=1;i<=n;i++) T[i]=0; w_time=0; ans=0; calc(1); printf("%d\n",ans); } return 0;}
- 【边分治】Kuala Lumpur 2008
- Regionals 2010, Asia - Kuala Lumpur
- Regional 2011, Asia - Kuala Lumpur 解题报告
- 20130831组队赛-(Kuala Lumpur Site) Asia Regional 2011
- 130831组队赛-Regionals 2011, Asia - Kuala Lumpur
- 2014 Asia Kuala Lumpur Regional Contest(吉隆坡2014)解题报告汇总
- 树分治(点分治+边分治)
- spoj qtree4 边分治
- bzoj2870 边分治
- 分治
- 分治
- 分治
- 分治
- 分治
- 分治
- 分治
- 分治
- 分治
- 58. 给未来的消息
- DataTable to byte[]、DataTable to XML(string)
- OpenCV 范例程序调试
- c#字符串常用汇总
- linux资源查看命令详解大全[top|vmstat|free]
- 【边分治】Kuala Lumpur 2008
- 思科TelePresence初体验
- UVALive 6042 Bee Tower
- 再议字节序-------TCP/IP网络传输相关字节序
- PLDA源代码分析(1)-PLDA_Train
- ajaxfileupload带参数上传文件
- Ubuntu 硬链接 和 软链接 的区别
- [c/c++]static的作用
- Linux FB 驱动讲解