zoukankan      html  css  js  c++  java
  • Luogu4149 [IOI2011]Race

    Luogu4149 [IOI2011]Race

    真真正正的淀粉质模板题。

    为什么?之前那个O(N^2)检验子树的算法对于菊花图就很呵呵。

    这个题,难点在于对子树的统计。

    我们无法使用容斥一类的思想。

    但是我们可以使用一种其他的方法。

    也就是利用其中一颗的子树与其他子树的信息进行统计答案。

    这样的话,就可以保证同一个子树内的信息不会被统计多次。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    /*using std::min;
    using std::max;*/
    
    const int N=201000;
    const int K=1010000;
    const int inf=0x7ffffff;
    
    struct node
    {
        int p;
        int value;
        int nxt;
    };
    
    node line[N<<1];
    int head[N],tail;
    int size[N],f[N],vis[N];
    int root,sum,ans;
    int T[K];
    int n,k;
    
    int max(int a,int b)
    {
        return a > b ? a : b ;
    }
    
    int min(int a,int b)
    {
        return a < b ? a : b ;
    }
    
    int read()
    {
        int res=0,flag=1;
        char c=getchar();
        while(c>'9'||c<'0')
        {
            if(c=='-') flag=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9')
        {
            res=(res<<1)+(res<<3)+c-'0';
            c=getchar();
        }
        return res*flag;
    }
    
    void add(int a,int b,int c)
    {
        line[++tail].p=b;
        line[tail].value=c;
        line[tail].nxt=head[a];
        head[a]=tail;
        return ;
    }
    
    void get_hry(int now,int fa)
    {
        size[now]=1;f[now]=0;
        int v;
        for(int i=head[now];i;i=line[i].nxt)
        {
            v=line[i].p;
            if(vis[v]||v==fa)   continue;
            get_hry(v,now);
            f[now]=max(f[now],size[v]);
            size[now]+=size[v];
        }
        f[now]=max(f[now],sum-size[now]);
        if(f[root]>f[now])  root=now;
        return ;
    }
    
    void get_DD(int now,int fa,int Dis,int Dep)
    {
        if(Dis>k)  return ;
        ans=min(ans,T[k-Dis]+Dep);
        int v;
        for(int i=head[now];i;i=line[i].nxt)
        {
            v=line[i].p;
            if(v==fa||vis[v])   continue;
            get_DD(v,now,Dis+line[i].value,Dep+1);
        }
        return ;
    }
    
    void updata(int now,int fa,int Dis,int Dep,int model)
    {
        if(Dis>k)    return ;
        if(model)   T[Dis]=min(T[Dis],Dep);
        else    T[Dis]=inf;
        int v;
        for(int i=head[now];i;i=line[i].nxt)
        {
            v=line[i].p;
            if(v==fa||vis[v])   continue;
            updata(v,now,Dis+line[i].value,Dep+1,model);
        }
        return ;
    }
    
    void solve(int now)
    {
        vis[now]=1;
        T[0]=0;
        int v;
        for(int i=head[now];i;i=line[i].nxt)
        {
            v=line[i].p;
            if(vis[v])  continue;
            get_DD(v,now,line[i].value,1);
            //ADD();
            updata(v,now,line[i].value,1,1);;
        }
        for(int i=head[now];i;i=line[i].nxt)
        {
            v=line[i].p;
            if(vis[v])  continue;
            updata(v,now,line[i].value,1,0);
        }
        for(int i=head[now];i;i=line[i].nxt)
        {
            v=line[i].p;
            if(vis[v])  continue;
            sum=size[v];root=0;
            get_hry(v,now);
            solve(root);
        }
        return ;
    }
    
    int main()
    {
        //scanf("%d%d",&n,&k);
        n=read(),k=read();
        for(int i=1;i<=k;i++)   T[i]=inf;
        for(int i=1,a,b,c;i<n;i++)
        {
            //scanf("%d%d%d",&a,&b,&c);
            a=read(),b=read(),c=read();
            add(a+1,b+1,c);
            add(b+1,a+1,c);
        }
        root=0;sum=n;
        f[0]=inf;ans=inf;
        get_hry(1,0);
        solve(root);
        if(ans!=inf)
            printf("%d",ans);
        else
            printf("-1");
        return 0;
    }
    
    
  • 相关阅读:
    linux 常用命令
    ubuntu 安装在硬盘与配置
    linux管道符、重定向与环境变量
    linux用户身份与文件权限
    centos开启ftp服务
    js实现常见排序算法
    算法分析
    Vim
    CSS的3种使用方法
    cookie 在登录时的存储,获取,清除
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/10293310.html
Copyright © 2011-2022 走看看