BZOJ 3124 [Sdoi2013]直径 DFS

来源:互联网 发布:淘宝客设置推广位 编辑:程序博客网 时间:2024/05/29 03:18

题意:

给定一棵树,求直径长度以及所有直径经过的边的个数。


解析:

第一问SB题,上树形DP或者任意挑选一个点,搜离他最远的点,再从该点搜离该点最远的点都可以。
我选择了后者。
因为第二问可以用到。
首先被所有直径都经过的边一定在一条直径上,且一定是连续的。
所以我们拿第一问随便搜出来的一条直径,扫描其上的所有点。
对于每一个点,我们搜离该点最远的点,并且不能够经过我们搜出来的这条直径。
那么如果这段距离等于该点到我们搜出来的直径的一个端点的
距离的话,那么该点到这个端点之间的所有边都不能称为答案。
因为我们无法走直径上的边,所以这个搜索的复杂度是O(n),
在加上第一问我们深搜两边的O(n)复杂度。
整体复杂度O(n)。


代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 200100using namespace std;typedef long long ll;int n,cnt;int head[N];struct node{    int from,to,next;    ll val;}edge[N<<1];void init(){    memset(head,-1,sizeof(head));    cnt=1;}void edgeadd(int from,int to,ll val){    edge[cnt].from=from,edge[cnt].to=to,edge[cnt].val=val;    edge[cnt].next=head[from];    head[from]=cnt++;}ll madis;int no1,no2;int f[N];int vis[N];void dfs1(int now,int ff,ll dis){    if(madis<dis)    {        madis=dis;        no1=now;    }    for(int i=head[now];i!=-1;i=edge[i].next)    {        int to=edge[i].to;        if(to==ff)continue;        dfs1(to,now,dis+edge[i].val);    }}void dfs2(int now,int ff,ll dis){    if(madis<dis)    {        madis=dis;        no2=now;    }    for(int i=head[now];i!=-1;i=edge[i].next)    {        int to=edge[i].to;        if(to==ff)continue;        f[to]=i;        dfs2(to,now,dis+edge[i].val);    }}ll newdis;void dfs3(int now,int ff,ll dis){    if(newdis<dis)    {        newdis=dis;    }    for(int i=head[now];i!=-1;i=edge[i].next)    {        int to=edge[i].to;        if(to==ff||vis[to])continue;        dfs3(to,now,dis+edge[i].val);    }}int main(){    init();    scanf("%d",&n);    for(int i=1;i<n;i++)    {        int u,v;        ll val;        scanf("%d%d%lld",&u,&v,&val);        edgeadd(u,v,val),edgeadd(v,u,val);    }    madis=-1;dfs1(1,0,0);    madis=-1;dfs2(no1,0,0);    printf("%lld\n",madis);    f[no1]=-1;    int cntgeshu=0;    for(int i=f[no2];i!=-1;i=f[edge[i].from])    {cntgeshu++;vis[edge[i].to]=1;}    vis[no1]=1;    int newcnt=0;    ll nowdis=0;    int l,r;    for(int i=f[no2];i!=-1;i=f[edge[i].from])    {        newcnt++;        nowdis+=edge[i].val;        newdis=0;        dfs3(edge[i].from,0,0);        if(newdis==nowdis)l=newcnt;        if(newdis==madis-nowdis)break;    }    printf("%d\n",newcnt-l);}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝认人晚上哭着找阿姨怎么办呀 在拼多多被商家威胁了怎么办 格来云游戏禁止改画质怎么办 京东换了手机登陆要安全验证怎么办 百度网盘登录总是需要验证码怎么办 在微信群发出视频无法撤回怎么办 百度网盘客户端说网络有风险怎么办 百度网盘绑定的手机号注销了怎么办 百度网盘绑定的手机号不用了怎么办 百度网盘内存怎么清空不了怎么办 百度网盘下载时本地空间不足怎么办 百度网盘文件放到桌面太大怎么办 百度有钱花借款没有钱还怎么办 安心流量包扣了两百多钱怎么办 邮箱里超大附件的文件过期了怎么办 ps时间轴储存出现参数错误怎么办 苹果手机网易云会员支付失败怎么办 鲸钱包网络异常需重新加载怎么办 微信加载联系人失败点击重试怎么办 网易将军令没有帐号怎么绑定怎么办 网易将军令绑定银行卡锁定了怎么办 网易新闻上的视频没有声音怎么办 把登录窗体的宏删掉了怎么办 电脑死机了怎么办也不能关机了 虎牙直播手游无法和队友开麦怎么办 为成年开无手续麽托出车祸怎么办 支付宝商户未签约或合约过期怎么办 我的手机帐号被锁定了怎么办 点错网页下载收发收费信息怎么办 用邮箱注册的微信忘记密码了怎么办 很久不用的邮箱号忘记密码怎么办 陕西省志愿云忘记密码和邮箱怎么办 国寿易学堂忘记登录密码怎么办 百度云下载显示本地空间不足怎么办 百度云离线内容违规无法下载怎么办 百度云压缩包要压解密码没有怎么办 用2016酷我音乐制作铃音怎么办 邮箱跟手机号一同绑定支付宝怎么办 网易邮箱取消账户关联没反应怎么办 剑三重置版客户端修复不成功怎么办 网易闪电邮的邮件满了怎么办