5.19[bzoj树网的核]
围观了final,SJTU还是飞了,泽民同志劲啊!
膜拜归膜拜...回来开题
bzoj1999树网的核
最近就喜欢给自己找切不动的题...QAQ
ok.....昨天在家里做了一个下午+晚上 又困&又累,虽然的确是调出了一些bug但是最sb的一句话今天才刚刚调出来...晕啊
finding my 状态ing...
联赛数据n=300,现在想想真是厚道,vijos也很厚道,一个完全通不过的程序居然还A了...
Demi Guo说过思考三部曲,想法是什么,想法怎么来的,我为什么想不到.
(证明一)核一定存在于直径上,并且存在于任何一条直径上.这个证明网上blog有很多,我贴一个我看过的.
第一步自然是找直径。我们实在是很想用Floyd来求直径,但N=300的范围在那里摆着,迫使我们要寻求更快的方法。我们注意到直径的一个性质:
对于直径中的任意一点,其距离树中其他点的最远距离不超过该点到达直径端点的距离。这是个显而易见的性质。由这个性质,我们可以导出如下引理:
对于树中的任意一点,距离其最远的点一定是树的直径的某一端点。
用同样的方法,我们很容易找到另一个端点,也就求出了直径。现在的问题是:直径可能有很多条,究竟取哪一条呢?其实任意一条都是可行的。我们做如下的说明:
首先,题目中告诉我们树的所有直径的中点必然重合,也就是告诉我们:所有的直径都是相交的。从而对于任意两条不同的直径,我们可以找到一个分叉点,我们记分叉部分的长度为L1,直径总长减去L1的长度记为L2。假设这个“核”没有经过分叉点,那么两种情况:
1、 在公共部分,其最小“偏心距”一定不大于L2;
2、 在分叉部分,其最小“偏心距”一定不小于L2。
假设这个“核”经过分叉点,那么其最小偏心距至少是L1。所以很明显,其最小“偏心距”所对应的“核”必然有一部分出现在所有直径的公共部分,而对于不完全在公共部分的“核”,其“偏心距”拥有同样的下界L1,也不会影响到最终结果。
还有一个比较形象直观的证明,传送门:http://blog.csdn.net/cyxhahaha/article/details/47345999
(证明二)核找得越长越好,这个很好理解.
在找核的时候,大家都用了单调队列,我比较弱..个人感觉rmq好理解..然后MLE...又辛辛苦苦地改成了线段树...
时间慢不多说
#include<cstdio>
#include<algorithm>
#define inf 1<<30
#define N 500100
using namespace std;
],vet[N*],pri[N*],u[N],arr[N],q[N*];
][],dis[][N],tree[N*];
void bfs(int st,int ed,int id)
{
,r=,now;q[]=st;u[st]=;dis[id][st]=;
while(l<=r)
{
now=q[l];int e=head[now];
)
{
int v=vet[e];
){
r++;q[r]=v;dis[id][v]=dis[id][now]+pri[e];u[v]=;
)if(v==ed)break;
}
e=next[e];
}
)if(q[r]==ed)break;
l++;
}
;i<=n;i++)u[i]=;
)
{
num[]=ed;num[]=;arr[ed]=;
;i;i--)][q[i]]+dis[][q[i]]==dis[][st]){//跟posa距离+跟posb距离==posa-posb
++num[];num[num[]]=q[i];arr[q[i]]=;
}
}
}
void add(int u,int v,int w)
{
edgenum++;vet[edgenum]=v;next[edgenum]=head[u];head[u]=edgenum;pri[edgenum]=w;
}
void bii(int x)
{
//printf("dis===%d\n",x);
u[x]=;int e=head[x];
)
{
int v=vet[e];
&&u[v]==)
{
bii(v);
f[x][]=max(f[x][],f[v][]+pri[e]);
}
e=next[e];
}
}
void update(int l,int r,int st,int ed,int p,int v)
{
if(l==st&&r==ed){
tree[p]=v;return;}
;
,ed,p+p+,v);else {
update(l,mid,st,mid,p+p,v);update(mid+,r,mid+,ed,p+p+,v);
}
])tree[p]=tree[p+p];];
}
int find(int l,int r,int st,int ed,int p)
{
if(l==st&&r==ed)return tree[p];
;
if(r<=mid)return find(l,r,st,mid,p+p);else
,ed,p+p+);else
,r,mid+,ed,p+p+));
}
int query(int st,int ed)
{
,k=;
tmp=find(st,ed,,num[],);
return tmp;
}
int main()
{
freopen("1999.in","r",stdin);
scanf("%d%d",&n,&s);int uu,vv,ww;
;i<=n-;i++)
{
scanf("%d%d%d",&uu,&vv,&ww);add(uu,vv,ww);add(vv,uu,ww);
}
bfs(,,);posa=;dis[][]=-;;i<=n;i++)][i]>dis[][posa])posa=i;
bfs(posa,,);posb=;dis[][]=-;;i<=n;i++)][i]>dis[][posb])posb=i;
bfs(posb,posa,);
//printf("%d %d\n",posa,posb);
;i<=num[];i++)bii(num[i]);
;i<=num[];i++)update(i,i,,num[],,f[num[i]][]);
,r=;int ans=inf;
//printf("dis===%d\n",f[2][0]);
])
{
r=max(r,l);
<=num[]&&(dis[][num[r+]]-dis[][num[l]])<=s)
{
r++;
}
ans=min(ans,max(dis[][posb]-dis[][num[r]],max(dis[][num[l]],query(l,r))));
l++;
}
printf("%d",ans);
}
5.19[bzoj树网的核]的更多相关文章
- [BZOJ1999][codevs1167][Noip2007]Core树网的核
[BZOJ1999][codevs1167][Noip2007]Core树网的核 试题描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(t ...
- BZOJ1999或洛谷1099&BZOJ2282或洛谷2491 树网的核&[SDOI2011]消防
一道树的直径 树网的核 BZOJ原题链接 树网的核 洛谷原题链接 消防 BZOJ原题链接 消防 洛谷原题链接 一份代码四倍经验,爽 显然要先随便找一条直径,然后直接枚举核的两个端点,对每一次枚举的核遍 ...
- bzoj1999 / P1099 树网的核
P1099 树网的核 (bzoj数据加强) 前置知识:树的直径 (并不想贴我的智障写法虽然快1倍但内存占用极大甚至在bzoj上MLE) 正常写法之一:用常规方法找到树的直径,在直径上用尺取法找一遍,再 ...
- 洛谷P1099 BZOJ1999 树网的核 [搜索,树的直径]
洛谷传送门,BZOJ传送门 树网的核 Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenetwork),其中V ...
- 树网的核[树 floyd]
描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并设T ...
- noip2007 树网的核
P1099 树网的核 112通过 221提交 题目提供者该用户不存在 标签动态规划树形结构2007NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录 题目描述 设T=(V, E, W) ...
- Cogs 97. [NOIP2007] 树网的核 Floyd
题目: http://cojs.tk/cogs/problem/problem.php?pid=97 97. [NOIP2007] 树网的核 ★☆ 输入文件:core.in 输出文件:core ...
- [bzoj1999]树网的核
从下午坑到网上..noip的数据太弱,若干的地方写挂结果还随便过= = 最坑的就是网上有些题解没考虑周全... 第一步是找直径,用两次bfs(或者dfs,Linux下系统栈挺大的..)解决.找出其中一 ...
- 洛谷 P1099 树网的核
P1099 树网的核 题目描述 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W ...
随机推荐
- win7下安装openpyxl
想使用python来操作Excel,看资料据说openpyxl非常好用,于是到https://pypi.python.org/pypi/openpyxl下载了安装包.下面就来说说安装步骤,也算是对自己 ...
- ios的链式编程笔记
1.Masonry的语法为啥能连续的使用点语法? >> 底层使用的是:用block当函数的返回参数 > 链式编程思想 2. 使用block当函数的返回参数 // 之前开发中比较习惯 ...
- [Java 基础] 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
reference : http://www.cnblogs.com/linjiqin/archive/2013/05/30/3108188.html 在Java多线程应用中,队列的使用率很高,多数生 ...
- elipse插件整理
整理一下用过的eclipse插件: 1. WindowBuilder :swing插件,可以拖啊拖啊拖出来一个窗口,可以显著提高开发效率. 官网: http://www.eclipse.org/w ...
- Android手绘效果实现
效果图 原理 大概介绍一下实现原理.首先你得有一张图(废话~),接下来就是把这张图的轮廓提取出来,轮廓提取算法有很多,本人不是搞图像处理的,对图像处理感兴趣的童鞋可以查看相关资料.如果你有好的轮廓提取 ...
- 三、jQuery--jQuery基础--jQuery基础课程--第8章 jQuery 实现Ajax应用
1.使用load()方法异步请求数据 使用load()方法通过Ajax请求加载服务器中的数据,并把返回的数据放置到指定的元素中,它的调用格式为:load(url,[data],[callback]) ...
- grep -i 不区分大小写
# rpm -qa|grep -i "mysql" MySQL-server--.rhel5.x86_64 MySQL-test--.rhel5.x86_64 MySQL-embe ...
- Linq to json
Json.Net系列教程 4.Linq To JSON 一.Linq to JSON是用来干什么的? Linq to JSON是用来操作JSON对象的.可以用于快速查询,修改和创建JSON对象.当JS ...
- Integer Inquiry【大数的加法举例】
Integer Inquiry Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 27730 Accepted: 10764 ...
- Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式
当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...