• #点分治#洛谷 4149 [IOI2011]Race


    题目

    给一棵树,每条边有权。求一条简单路径,权值和等于 (k),且边的数量最小。


    分析

    点分治,记录一定权值的最小边数量,
    每遍历一棵子树后统计答案


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=200011; bool v[N]; struct node{int y,w,next;}e[N<<1];
    int big[N],siz[N],SIZ,root,tot,ans,w[N*5],dep[N],dis[N],n,m,as[N],et=1;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans; 
    }
    inline void Max(int &a,int b){a=a>b?a:b;}
    inline void Min(int &a,int b){a=a<b?a:b;}
    inline void dfs(int x,int fa){
    	siz[x]=1,big[x]=0;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fa&&!v[e[i].y]){
    		dfs(e[i].y,x);
    		siz[x]+=siz[e[i].y];
    		Max(big[x],siz[e[i].y]);
    	}
    	Max(big[x],SIZ-siz[x]);
    	if (big[x]<big[root]) root=x;
    }
    inline void Get(int x,int fa,int Dis,int Dep){
    	if (Dis>m) return;
    	dis[++tot]=Dis,dep[tot]=Dep;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (e[i].y!=fa&&!v[e[i].y])
    	    Get(e[i].y,x,Dis+e[i].w,Dep+1);
    }
    inline void calc(int x){
    	w[0]=tot=0;
    	for (rr int i=as[x];i;i=e[i].next)
    	if (!v[e[i].y]){
    		rr int Tot=tot;
    		Get(e[i].y,x,e[i].w,1);
    		for (rr int j=Tot+1;j<=tot;++j) Min(ans,w[m-dis[j]]+dep[j]);
    		for (rr int j=Tot+1;j<=tot;++j) Min(w[dis[j]],dep[j]);
    	}
    	for (rr int i=1;i<=tot;++i) w[dis[i]]=w[m+1];
    }
    inline void dp(int x){
    	v[x]=1,calc(x);
    	for (rr int i=as[x];i;i=e[i].next)
    	if (!v[e[i].y]){
    		big[0]=SIZ=siz[e[i].y];
    		dfs(e[i].y,root=0),dp(root);
    	}
    }
    signed main(){
    	n=iut(),m=iut(),ans=n+1;
    	for (rr int i=1;i<=m+1;++i) w[i]=ans;
    	for (rr int i=1;i<n;++i){
    		rr int x=iut()+1,y=iut()+1,w=iut();
    		e[++et]=(node){y,w,as[x]},as[x]=et;
    		e[++et]=(node){x,w,as[y]},as[y]=et;
    	}
    	big[0]=SIZ=n,dfs(1,root=0),dp(root);
    	if (ans>n) printf("-1");
    	    else printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    Windows10切换其他用户身份运行程序
    管理Windows功能
    如何暂时锁定您的键盘
    判断远程计算机基于x64或x86处理器
    复制文件而不在命令行中覆盖它们
    解决IDEA Gradle工程控制台输出乱码
    jquery 选择器、属性和CSS、文档处理、筛选、事件、动画效果
    IDEA炫酷主题推荐!(转)
    Windows 查看端口占用进程并关闭(转)
    JVM(二)--运行时数据区
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14480160.html
Copyright © 2020-2023  润新知