• BZOJ3124: [Sdoi2013]直径


    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3124

    首先第一问直接求直径就可以了。

    然后对于第二问,因为直径一定过树的重心,于是可以把重心找出来。

    如果是菊花图的话,那就输出0。。

    如果不是菊花图,对于很多条直径的两个端点,一定可以把它们分成两个点集使得每个点到对面点集的任一个点的路径都是直径。。

    于是这两个点集分别求lca,两个lca之间的距离就是答案了。

    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define inf 1000000007
    #define ll long long
    #define maxn 200500
    #define eps 1e-5
    #define mm 2147483648
    #define low(x) (x&(-x))
    #define f(x,y,z) g[x][y][z+8]
    using namespace std;
    struct data{int obj,pre; ll c;
    }e[maxn*2];
    ll diss[maxn],dist[maxn],len;
    int mx[maxn],head[maxn],qs[maxn],qt[maxn],sz[maxn],dep[maxn],bin[30],fa[maxn][30];
    int s,t,n,cnt1,cnt2,tot,root;
    ll read(){
        ll x=0,f=1; char ch=getchar();
        while (!isdigit(ch)){if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    void insert(int x,int y,ll z){
        e[++tot].obj=y; e[tot].pre=head[x]; e[tot].c=z; head[x]=tot;
    }
    int dfs(int s,ll dis[]){
        queue<int > q; q.push(s);
        rep(i,1,n) dis[i]=inf; dis[s]=0;
        int mx=0,ans=0;
        while (!q.empty()){
            int u=q.front(); q.pop();
            for (int j=head[u];j;j=e[j].pre){
                int v=e[j].obj;
                if (dis[v]==inf) {
                    dis[v]=dis[u]+e[j].c; q.push(v);
                    if (dis[v]>mx) mx=dis[v],ans=v;
                }
            }
        }
        return ans;
    }
    void get(int u,int f){
        sz[u]++;
        for (int j=head[u];j;j=e[j].pre){
            int v=e[j].obj;
            if (v!=f) {
                get(v,u);
                sz[u]+=sz[v]; mx[u]=max(mx[u],sz[v]);
            }
        }
        mx[u]=max(mx[u],n-sz[u]);
    }
    void dfs(int u){
        rep(i,1,20) if (dep[u]>=bin[i]) fa[u][i]=fa[fa[u][i-1]][i-1];
        for (int j=head[u];j;j=e[j].pre){
            int v=e[j].obj;
            if (v!=fa[u][0]){
                fa[v][0]=u; dep[v]=dep[u]+1;
                dfs(v);
            }
        }
    }
    int lca(int x,int y){
        if (dep[x]<dep[y]) swap(x,y);
        int t=dep[x]-dep[y];
        rep(i,0,20) if (t&bin[i]) x=fa[x][i];
        down(i,20,0) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
        if (x==y) return x;
        return fa[x][0];
    }
    int main(){
    //  freopen("diameter.in","r",stdin);
    //  freopen("diameter.out","w",stdout);
        bin[0]=1; rep(i,1,20) bin[i]=bin[i-1]*2;
        n=read();
        rep(i,1,n-1){
            int x=read(),y=read();ll z=read();
            insert(x,y,z); insert(y,x,z);
        }
        s=dfs(1,diss);
        t=dfs(s,diss); dfs(t,dist);
        len=diss[t]; printf("%lld
    ",len);
        rep(i,1,n){
            if (diss[i]==len&&dist[i]==len) {puts("0"); return 0;}
            if (diss[i]==len) qs[++cnt1]=i;
            if (dist[i]==len) qt[++cnt2]=i;
        }
        root=0; mx[0]=inf;
        get(s,0);
        rep(u,1,n)  if (mx[root]>mx[u]) root=u;
    //  printf("%d
    ",root);
        dfs(root);
        int a,b;
        if (cnt1==1) a=qs[cnt1];
        else {
            a=lca(qs[1],qs[2]);
            rep(i,3,cnt1) a=lca(a,qs[i]);
        }
        if (cnt2==1) b=qt[cnt2];
        else {
            b=lca(qt[1],qt[2]);
            rep(i,3,cnt2) b=lca(b,qt[i]);
        }
        printf("%d
    ",dep[a]+dep[b]-2*dep[lca(a,b)]);
        return 0;
    }
  • 相关阅读:
    myfocus官方网站已经挂掉,相关下载已经从googlecode转到网盘
    [综合]visio2013安装提示找不到Office.zh_cnofficeMUI.mis officemui.xml
    技巧分享:解决Word 2010当中“分页符”造成的空白行
    房贷计算器代码2.0
    房贷计算器代码
    图解-JS普通函数跟箭头函数中this的指向问题
    完全基于net core容器的超级轻量化的Quartz,支持类似net core mvc的过滤器,附过滤器实现源码
    net下的高性能轻量化半自动orm+linq的《SqlBatis》
    轻量级ORM《sqlcommon》第一个版本发布了!!!
    从0开始编写dapper核心功能、压榨性能、自己动手丰衣足食
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5160272.html
Copyright © 2020-2023  润新知