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

    (color{#0066ff}{题目描述})

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

    (color{#0066ff}{输入格式})

    第一行:两个整数 n,k。

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

    (color{#0066ff}{输出格式})

    一个整数,表示最小边数量。

    如果不存在这样的路径,输出 -1。

    (color{#0066ff}{输入样例})

    4 3
    0 1 1
    1 2 2
    1 3 4
    

    (color{#0066ff}{输出样例})

    2
    

    (color{#0066ff}{数据范围与提示})

    n≤200000,K≤1000000。

    (color{#0066ff}{题解})

    点分治

    每次选出重心,对子树进行操作

    搜每棵子树,把所有的dis和dep放进一个数组里(pair存)

    开一个数组t,t[i]代表,到当前重心的距离为i的最少边数

    每次搜完一棵子树,就用t和当前的结果更新ans

    然后把当前子树的信息加入t

    每次work的时候要把t清空(赋成极大值)

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    LL in() {
    	char ch; int x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    
    struct node {
    	int to, dis;
    	node *nxt;
    	node(int to = 0, int dis = 0, node *nxt = NULL): to(to), dis(dis), nxt(nxt) {}
    	void *operator new (size_t) {
    		static node *S = NULL, *T = NULL;
    		return (S == T) && (T = (S = new node[1024]) + 1024), S++;
    	}
    };
    const int N = 2e5 + 10;
    const int M = 1e6 + 10;
    const int inf = 0x7f7f7f7f;
    int siz[N], t[M], f[N], tmp[N];
    using std::pair;
    using std::make_pair;
    pair<int, int> ls[N];
    node *head[N];
    bool vis[N];
    int n, k, num, sum, root, cnt;
    int ans = inf;
    void add(int from, int to, int dis) {
    	head[from] = new node(to, dis, head[from]);
    }
    void getdis(int x, int fa, int dis, int dep) {
    	ls[++cnt] = make_pair(dis, dep);
    	tmp[++num] = dis;
    	for(node *i = head[x]; i; i = i->nxt) 
    		if(i->to != fa && !vis[i->to]) 
    			getdis(i->to, x, dis + i->dis, dep + 1);
    }
    void getroot(int x, int fa) {
    	f[x] = 0;
    	siz[x] = 1;
    	for(node *i = head[x]; i; i = i->nxt) {
    		if(i->to == fa || vis[i->to]) continue;
    		getroot(i->to, x);
    		siz[x] += siz[i->to];
    		f[x] = std::max(f[x], siz[i->to]);
    	}
    	f[x] = std::max(f[x], sum - siz[x]);
    	if(f[x] < f[root]) root = x;
    }
    void calc(int x) {
    	num = 0;
    	for(node *i = head[x]; i; i = i->nxt) {
    		if(vis[i->to]) continue;
    		cnt = 0;
    		getdis(i->to, 0, i->dis, 1);
    		for(int j = 1; j <= cnt; j++) 
    			if(ls[j].first <= k) 
    				ans = std::min(ans, ls[j].second + t[k - ls[j].first]);
    		for(int j = 1; j <= cnt; j++) 
    			if(ls[j].first <= k) 
    				t[ls[j].first] = std::min(t[ls[j].first], ls[j].second);
    	}
    	for(int i = 1; i <= num; i++) if(tmp[i] <= k) t[tmp[i]] = inf;
    }
    void work(int x) {
    	vis[x] = true;
    	calc(x);
    	for(node *i = head[x]; i; i = i->nxt) {
    		if(vis[i->to]) continue;
    		root = 0, sum = siz[i->to];
    		getroot(i->to, 0);
    		work(root);
    	}
    }
    int main() {
    	n = in(), k = in();
    	int x, y, z;
    	for(int i = 1; i < n; i++) {
    		x = in(), y = in(), z = in();
    		add(x + 1, y + 1, z), add(y + 1, x + 1, z);
    	}
    	for(int i = 1; i <= k; i++) t[i] = inf;
    	f[0] = sum = n;
    	getroot(1, 0);
    	work(root);
    	printf("%d", ans == inf? -1 : ans);
    	return 0;
    }
    
  • 相关阅读:
    02.创建型————工厂方法模式
    01.创建型————简单工厂模式
    HBase JavaAPI操作示例
    MongoDB
    大数据第三天
    Zookeeper操作
    MR操作
    HDFS操作
    【GISER&&Painter】svg的那些事
    读法克鸡丝博文《技术,产品,团队》有感
  • 原文地址:https://www.cnblogs.com/olinr/p/10208298.html
Copyright © 2011-2022 走看看