• BZOJ2599: [IOI2011]Race


    【传送门:BZOJ2599


    简要题意:

      给出一棵n个点的树,和每条边的边权

      求出所有距离为k的点对中,两个点之间的最少边数


    题解:

      点分治好题

      设c[i]为当前点分治的时候与根的距离为i的最小边数

      因为我们不能使得求出来的点对都在一棵子树里面,所以我们枚举每一棵与根相连的子树,每次求出对于这棵子树的c数组

      然后再DFS一遍,更新答案

      听说不能用memset来初始化c,那么就DFS将用过的位置初始化


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define INF 1<<31-1
    using namespace std;
    struct node
    {
        int x,y,d,next;
    }a[410000];int len,last[210000];
    void ins(int x,int y,int d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    }
    int tot[210000],root,sum,ms[210000];
    bool v[210000];
    void getroot(int x,int fa)
    {
        tot[x]=1;ms[x]=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa&&v[y]==false)
            {
                getroot(y,x);
                tot[x]+=tot[y];
                ms[x]=max(ms[x],tot[y]);
            }
        }
        ms[x]=max(ms[x],sum-tot[x]);
        if(ms[root]>ms[x]) root=x;
    }
    int ans,k;
    int c[1100000];
    int dep[210000],d[210000];
    void cal(int x,int fa)
    {
        if(d[x]<=k) ans=min(ans,c[k-d[x]]+dep[x]);
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa&&v[y]==false)
            {
                dep[y]=dep[x]+1;
                d[y]=d[x]+a[k].d;
                cal(y,x);
            }
        }
    }
    void change(int x,int fa,int t)
    {
        if(d[x]<=k)
        {
            if(t==0) c[d[x]]=min(c[d[x]],dep[x]);
            else c[d[x]]=INF;
        }
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa&&v[y]==false)
            {
                change(y,x,t);
            }
        }
    }
    void solve(int x)
    {
        v[x]=true;c[0]=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(v[y]==false)
            {
                dep[y]=1;d[y]=a[k].d;
                cal(y,0);
                change(y,0,0);
            }
        }
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(v[y]==false)
            {
                change(y,0,1);
            }
        }
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(v[y]==false)
            {
                sum=tot[y];
                root=0;getroot(y,x);
                solve(root);
            }
        }
    }
    int main()
    {
        int n;
        scanf("%d%d",&n,&k);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<n;i++)
        {
            int x,y,d;
            scanf("%d%d%d",&x,&y,&d);
            x++;y++;
            ins(x,y,d);ins(y,x,d);
        }
        memset(v,false,sizeof(v));
        memset(c,63,sizeof(c));c[0]=0;
        ans=sum=ms[0]=n;
        root=0;getroot(1,0);
        solve(root);
        if(ans!=n) printf("%d
    ",ans);
        else printf("-1
    ");
        return 0;
    }

     

  • 相关阅读:
    Hibernate中session的产生的方式
    Hibernate 多对多关联Demo
    Hibernate 一对多双向关联Demo
    Beta(0/7)
    获得小黄衫感想(2)
    软工实践作业(十)
    成员交换情况
    Alpha事后诸葛亮
    Alpha冲刺总结
    Alpha(10/10)
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8964415.html
Copyright © 2020-2023  润新知