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

    http://www.lydsy.com/JudgeOnline/problem.php?id=2599

    点分治

    mi[i] 记录边权和为i时的最少边数

    先更新答案,再更新mi数组,换根时清空mi

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    
    using namespace std;
    
    #define N 200001
    #define K 1000001
    
    int m;
    
    int front[N],nxt[N<<1],to[N<<1],tot,val[N<<1];
    
    bool vis[N];
    
    int f[N],siz[N];
    
    int root,all;
    int ans=N;
    
    int mi[K];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c))  { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=w;
    }
    
    void getroot(int x,int y)
    {
        //printf("%d
    ",x);
        siz[x]=1; f[x]=0;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=y && !vis[to[i]]) 
            {
                getroot(to[i],x);
                siz[x]+=siz[to[i]];
                f[x]=max(f[x],siz[to[i]]);
            }
        f[x]=max(f[x],all-siz[x]);
        if(f[x]<f[root]) root=x;
    }
    
    void dfs(int x,int y,int dis,int sum,int ty)
    {
        if(ty==1 && dis==m) ans=min(ans,sum);
        if(dis>=m) return;
        if(ty==1)
        {
            if(mi[m-dis]) ans=min(ans,sum+mi[m-dis]);
        }
        else if(ty==2) mi[dis]=mi[dis] ? min(mi[dis],sum) : sum;
        else mi[dis]=0;
        for(int i=front[x];i;i=nxt[i])
            if(to[i]!=y && !vis[to[i]]) dfs(to[i],x,dis+val[i],sum+1,ty);
    }
    
    void cal(int x)
    {
        for(int i=front[x];i;i=nxt[i])
            if(!vis[to[i]]) 
            {
                dfs(to[i],x,val[i],1,1);
                dfs(to[i],x,val[i],1,2);
            }
        for(int i=front[x];i;i=nxt[i])
            if(!vis[to[i]]) dfs(to[i],x,val[i],1,3);
    }
    
    void work(int x)
    {
    //    printf("%d
    ",x);
        cal(x);
        vis[x]=true;
        for(int i=front[x];i;i=nxt[i])    
            if(!vis[to[i]])
            {
                all=siz[to[i]];
                root=0;
                getroot(to[i],0);
                work(root);
            }
    }
    
    int main()
    {
        int size = 128 << 20;
        char *p = (char*)malloc(size) + size;  
        __asm__("movl %0, %%esp
    " :: "r"(p));
        freopen("ioi2011-race.in","r",stdin);
        freopen("ioi2011-race.out","w",stdout);
        int n;
        read(n);
        read(m);
        int u,v,w;
        for(int i=1;i<n;++i)
        {
            read(u); u++;
            read(v); v++;
            read(w);
            add(u,v,w);    
        }
        all=n;
        f[0]=n;
        getroot(1,0);
        work(root);
        printf("%d",ans==N ? -1 : ans);
    }
  • 相关阅读:
    顺序容器添加,查询,删除元素
    使用fiddler对app做弱网测试
    工作总结
    软件测试面试题_3
    软件测试面试题_2
    软件测试面试题_1
    MySQL的下载及安装
    关于let以及var的区别
    关于获取各种浏览器可见窗口大小的一点点研究
    log4J指定类下面的日志分隔
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8136142.html
Copyright © 2011-2022 走看看