首页 > 代码库 > [Sdoi2013]直径(树的直径)

[Sdoi2013]直径(树的直径)

 

//36分

#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<algorithm>#include<map>using namespace std;typedef long long ll;#define setfire(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout);#define fre(name) freopen(#name".txt","r",stdin);#ifdef WIN32#define LL "%lld"#else#define LL "%I64d"#endifconst int N=2e5+5;const int Z=2005;int n,S1,S2,la,lb,s_cnt,b[N],stack[N],prev[N];char s[50];bool vis[N];struct edge{int u,v,next;ll w;}e[N<<1];int tot=1,head[N];int dep[N],fa[N][19];ll ans,LEN,dis[N],dist[N];bool mark[Z][Z];struct data{int x,y;}state[N];inline int read(){    int x=0;char ch=getchar();    while(ch<0||ch>9){ch=getchar();}    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}    return x;}inline void add(int x,int y,int z){    e[++tot].u=x;e[tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot;    e[++tot].u=y;e[tot].v=x;e[tot].w=z;e[tot].next=head[y];head[y]=tot;}void BFS(int S){    int top=1;    stack[top]=S;dep[S]=1;fa[S][0]=S;    while(top){        int x=stack[top--];        for(int i=head[x];i;i=e[i].next){            if(e[i].v!=fa[x][0]){                fa[e[i].v][0]=x;                dep[e[i].v]=dep[x]+1;                dist[e[i].v]=dist[x]+e[i].w;                stack[++top]=e[i].v;            }        }    }}inline int bfs(int S){    memset(dis,-1,sizeof dis);    memset(vis,0,sizeof vis);    int id=0,mx=-1,top=1;    stack[top]=S;dis[S]=0;vis[S]=1;    while(top){        int x=stack[top--];        for(int i=head[x];i;i=e[i].next){            if(!vis[e[i].v]&&dis[e[i].v]<dis[x]+e[i].w){                vis[e[i].v]=1;                dis[e[i].v]=dis[x]+e[i].w;                if(dis[e[i].v]>mx) mx=dis[e[i].v],id=e[i].v;                stack[++top]=e[i].v;            }        }    }    return id;}void gosolve(int S,int T){    memset(vis,0,sizeof vis);    int id=0,mx=-1,top=1;    stack[top]=S;vis[S]=1;    while(top){        int x=stack[top--];        for(int i=head[x];i;i=e[i].next){            if(!vis[e[i].v]){                vis[e[i].v]=1;                prev[e[i].v]=i;                if(e[i].v==T){top=0;break;}                 stack[++top]=e[i].v;            }        }    }    for(int i=T;i!=S;i=e[prev[i]^1].v)  b[prev[i]>>1]++;} int lca(int a,int b){    if(dep[a]<dep[b]) swap(a,b);    int t=dep[a]-dep[b];    for(int i=0;i<=18;i++){        if(t&(1<<i)){            a=fa[a][i];        }    }    if(a==b) return a;    for(int i=18;i>=0;i--){        if(fa[a][i]!=fa[b][i]){            a=fa[a][i];            b=fa[b][i];        }    }    return fa[a][0];}void init(){    n=read();    for(int i=1,x,y,z;i<n;i++) x=read(),y=read(),z=read(),add(x,y,z);}void dp_tree_len(int x,int fa){    for(int i=head[x],y;i;i=e[i].next){        if((y=e[i].v)!=fa){            if((x==la&&y==lb)||(x==lb&&y==la)) continue;            dp_tree_len(y,x);            LEN=max(LEN,dis[x]+dis[y]+e[i].w);            dis[x]=max(dis[x],dis[y]+e[i].w);        }    }}void work(){    if(n<=100){        BFS(1);        for(int i=1,mx=0;i<=n;i++) if(dist[i]>mx) mx=dist[i],S1=i;        S2=bfs(S1);        LEN=dis[S2];        printf("%I64d\n",LEN);        for(int j=1;j<=18;j++){            for(int i=1;i<=n;i++){                fa[i][j]=fa[fa[i][j-1]][j-1];            }        }        ll lt;        for(int i=1,anc;i<=n;i++){            for(int j=1;j<i;j++){                if(mark[i][j]) continue;                anc=lca(i,j);                lt=dist[i]+dist[j]-dist[anc]*2;                if(lt==LEN) mark[i][j]=1,state[++s_cnt]=(data){i,j};            }        }            //直径条数         for(int i=1;i<=s_cnt;i++){            gosolve(state[i].x,state[i].y);        }        int num=0;        for(int i=1;i<=n;i++) if(b[i]==s_cnt) num++;        printf("%d",num);    }    else{        dp_tree_len(1,1);        printf("%I64d\n",LEN);    }}int main(){    freopen("diameter.in","r",stdin);    freopen("diameter.out","w",stdout);    int size=64<<20;    char *p=(char*)malloc(size)+size;    __asm__("movl %0,%%esp\n"::"r"(p));    init();    work();    return 0;} 

 

[Sdoi2013]直径(树的直径)