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

    Description

    给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000

    Input

    第一行 两个整数 n, k
    第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)

    Output

    一个整数 表示最小边数量 如果不存在这样的路径 输出-1

    Sample Input

    4 3
    0 1 1
    1 2 2
    1 3 4
    

    Sample Output

    2
    

    Solution

    点分治,基本上是个板子。。

    开个桶(g[i])记录路径长度为(i)边数最少是多少。

    注意无论怎么样(g[0])都会等于(0),不要被边权为(0)的边影响了。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 1e6+10;
    const int maxm = 1e6+10;
    const int inf = 1e9;
    
    int vis[maxn],f[maxn],sz[maxn],g[maxm],head[maxn],tot,n,k,rt,size,ans=1e9;
    struct edge{int to,nxt,w;}e[maxn<<1];
    
    void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
    void ins(int u,int v,int w) {add(u,v,w),add(v,u,w);}
    
    void get_rt(int x,int fa) {
    	sz[x]=1,f[x]=0;
    	for(int i=head[x];i;i=e[i].nxt)
    		if((!vis[e[i].to])&&e[i].to!=fa) 
    			get_rt(e[i].to,x),sz[x]+=sz[e[i].to],f[x]=max(f[x],sz[e[i].to]);
    	f[x]=max(f[x],size-sz[x]);
    	if(f[x]<f[rt]) rt=x;
    }
    
    void get_sz(int x,int fa) {
    	sz[x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    		if((!vis[e[i].to])&&e[i].to!=fa) get_sz(e[i].to,x),sz[x]+=sz[e[i].to];
    }
    
    void get_ans(int x,int fa,int dep,int dis) {
    	if(dis>k) return ;
    	ans=min(ans,dep+g[k-dis]);
    	for(int i=head[x];i;i=e[i].nxt)
    		if((!vis[e[i].to])&&e[i].to!=fa) get_ans(e[i].to,x,dep+1,dis+e[i].w);
    }
    
    void get_dp(int x,int fa,int dep,int dis) {
    	if(dis>k) return ;
    	g[dis]=min(g[dis],dep);
    	for(int i=head[x];i;i=e[i].nxt)
    		if((!vis[e[i].to])&&e[i].to!=fa) get_dp(e[i].to,x,dep+1,dis+e[i].w);
    }
    
    void clear(int x,int fa,int dis) {
    	if(dis>k) return ;
    	g[dis]=inf;
    	for(int i=head[x];i;i=e[i].nxt)
    		if((!vis[e[i].to])&&e[i].to!=fa) clear(e[i].to,x,dis+e[i].w);
    }
    
    void solve(int x) {
    	vis[x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to]) g[0]=0,get_ans(e[i].to,x,1,e[i].w),get_dp(e[i].to,x,1,e[i].w);
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to]) clear(e[i].to,x,e[i].w);
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!vis[e[i].to]) 
    			get_sz(e[i].to,0),size=sz[e[i].to],rt=0,get_rt(e[i].to,0),solve(rt);
    }
    
    int main() {
    	read(n),read(k);memset(g,63,sizeof g);g[0]=0;
    	for(int x,y,z,i=1;i<n;i++) read(x),read(y),read(z),ins(x+1,y+1,z);
    	size=n,f[0]=maxn+1,rt=0,get_rt(1,0),solve(rt);write(ans==inf?-1:ans);
    	return 0;
    }
    
  • 相关阅读:
    Passing structures between C# and C/C++
    Leetcode 题目整理-6 Swap Nodes in Pairs & Remove Duplicates from Sorted Array
    Leetcode 题目整理-5 Valid Parentheses & Merge Two Sorted Lists
    链表
    Leetcode 题目整理-4 Longest Common Prefix & Remove Nth Node From End of List
    Leetcode 题目整理-3 Palindrome Number & Roman to Integer
    Leetcode 题目整理-2 Reverse Integer && String to Integer
    Leetcode 题目整理-1
    Leetcode 题目整理
    static静态变量在c++类中的应用实例
  • 原文地址:https://www.cnblogs.com/hbyer/p/10185721.html
Copyright © 2011-2022 走看看