码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3124 SDOI2013 直径

时间:2016-04-14 22:18:32      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:

首先直径是很好求的,先以任意点为根DFS求出最远点,再以最远点为根求出第二个点

两个点之间的距离即为直径

显然对于第二问,答案是直径上的某一段,且满足不可向左右扩展出跟直径等长的路径

那么我们就可以暴力枚举直径上的点,看看它是否可以向右和向左扩展即可

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
 
typedef long long LL;
const int maxn=200010;
int n,u,v,w;
int A,B,L,ans;
int h[maxn],cnt=1;
struct edge{
    int to,next,w;
}G[maxn<<1];
LL dis[maxn],now,tmp,D;
int fa[maxn];
bool vis[maxn];
void add(int x,int y,int z){++cnt;G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt;}
void read(int &num){
    num=0;char ch=getchar();
    while(ch<‘!‘)ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-‘0‘,ch=getchar();
}
void DFS(int u,int f,int &c){
    if(dis[u]>now)now=dis[u],c=u;
    for(int i=h[u];i;i=G[i].next){
        int v=G[i].to;
        if(v==f)continue;
        dis[v]=dis[u]+G[i].w;
        fa[v]=i;
        DFS(v,u,c);
    }return;
}
void Get_Len(){
    now=-1;dis[1]=0;fa[1]=0;DFS(1,-1,A);
    now=-1;dis[A]=0;fa[A]=0;DFS(A,-1,B);
    printf("%lld\n",dis[B]);D=dis[B];
}
void check(int u,int f){
    if(dis[u]>tmp)tmp=dis[u];
    for(int i=h[u];i;i=G[i].next){
        int v=G[i].to;
        if(v==f)continue;
        if(vis[v])continue;
        dis[v]=dis[u]+G[i].w;
        check(v,u);
    }return;
}
void Get_ans(){
    now=0;
    for(int i=B;i;i=G[fa[i]^1].to)vis[i]=true;
    for(int i=fa[B];i;i=fa[G[i^1].to]){
        ans++;now+=G[i].w;
        tmp=-1;dis[G[i^1].to]=0;
        check(G[i^1].to,-1);
        if(tmp==now)L=ans;
        if(tmp==D-now)break;
    }printf("%d\n",ans-L);
}
 
int main(){
    read(n);
    for(int i=1;i<n;++i){
        read(u);read(v);read(w);
        add(u,v,w);add(v,u,w);
    }
    Get_Len();Get_ans();
    return 0;
}

  

 

BZOJ 3124 SDOI2013 直径

标签:

原文地址:http://www.cnblogs.com/joyouth/p/5392757.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!