• [Luogu4149][IOI2011]Race


    BZOJ权限题qwq
    Luogu

    sol

    树上路径当然是淀粉质辣!
    考虑所有过重心的路径。开一个(10^6)大小的数组(t)表示某一路径长度的最小边数,初始化为(inf(i>0))(t[0]=0)
    枚举重心的每棵子树进行(dfs),假设获得了一条从重心出发边数为(dep)边权和为(dis)的路径,就可以用(t[K-dis]+dep)更新答案。
    更新完答案后对应用(dep)更新(t[dis])
    记得还原(t)数组。显然不能直接memset设为(inf)。只需把更改过的位置改成(inf)即可。

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int gi()
    {
        int x=0,w=1;char ch=getchar();
        while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
        if (ch=='-') w=0,ch=getchar();
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return w?x:-x;
    }
    const int inf = 1e9;
    const int N = 2e5+5;
    int n,k,to[N<<1],nxt[N<<1],len[N<<1],head[N],cnt;
    int sz[N],w[N],root,sum,vis[N],t[N*5],ans=inf;
    void link(int u,int v,int ww)
    {
    	to[++cnt]=v;nxt[cnt]=head[u];len[cnt]=ww;
    	head[u]=cnt;
    }
    void getroot(int u,int f)
    {
    	sz[u]=1;w[u]=0;
    	for (int e=head[u];e;e=nxt[e])
    	{
    		int v=to[e];if (v==f||vis[v]) continue;
    		getroot(v,u);
    		sz[u]+=sz[v];w[u]=max(w[u],sz[v]);
    	}
    	w[u]=max(w[u],sum-sz[u]);
    	if (w[u]<w[root]) root=u;
    }
    void getans(int u,int f,int dep,int dis)
    {
    	if (dis>k) return;
    	ans=min(ans,t[k-dis]+dep);
    	for (int e=head[u];e;e=nxt[e])
    	{
    		int v=to[e];if (v==f||vis[v]) continue;
    		getans(v,u,dep+1,dis+len[e]);
    	}
    }
    void getdp(int u,int f,int dep,int dis)
    {
    	if (dis>k) return;
    	t[dis]=min(t[dis],dep);
    	for (int e=head[u];e;e=nxt[e])
    	{
    		int v=to[e];if (v==f||vis[v]) continue;
    		getdp(v,u,dep+1,dis+len[e]);
    	}
    }
    void clear(int u,int f,int dep,int dis)
    {
    	if (dis>k) return;
    	t[dis]=inf;
    	for (int e=head[u];e;e=nxt[e])
    	{
    		int v=to[e];if (v==f||vis[v]) continue;
    		clear(v,u,dep+1,dis+len[e]);
    	}
    }
    void solve(int u)
    {
    	vis[u]=1;
    	for (int e=head[u];e;e=nxt[e])
    		if (!vis[to[e]])
    			getans(to[e],u,1,len[e]),getdp(to[e],u,1,len[e]);
    	for (int e=head[u];e;e=nxt[e])
    		if (!vis[to[e]])
    			clear(to[e],u,1,len[e]);
    	for (int e=head[u];e;e=nxt[e])
    	{
    		int v=to[e];if (vis[v]) continue;
    		sum=sz[v];root=0;
    		getroot(v,0);
    		solve(root);
    	}
    }
    int main()
    {
    	n=gi();k=gi();
    	for (int i=1,u,v,ww;i<n;++i)
    	{
    		u=gi()+1;v=gi()+1;ww=gi();
    		link(u,v,ww);link(v,u,ww);
    	}
    	for (int i=1;i<=k;++i) t[i]=inf;
    	sum=w[0]=n;
    	getroot(1,0);
    	solve(root);
    	printf("%d
    ",ans==inf?-1:ans);
    	return 0;
    }
    
  • 相关阅读:
    Oracle 11G单机 无网络环境静默安装
    Centos 7 编译安装llvm 8.0.0
    linux下测试读写
    Linux 初始化 init 系统(1):sysvinit
    自动挂载文件/etc/fstab功能详解
    虚拟机安装LINUX网络配置注意的问题
    rhel7报错整理
    16/4/4二代支付硬盘故障处理
    RedHat Enterprise Linux 7关闭防火墙方法
    Linux命令之awk数组使用范例
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8463265.html
Copyright © 2020-2023  润新知