P4149 [IOI2011]Race

  对于这道题,明显是点分治,权值等于k,可以用桶统计树上路径(但注意要清空);

对于每颗子树,先与之前的子树拼k,再更新桶,维护t["len"]最小边数;

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define up(i,l,r) for(register int i = (l); i <= (r); ++i)
 4 #define dn(i,l,r) for(register int i = (l); i >= (r); --i)
 5 #define ll long long
 6 #define re register
 7 using namespace std;
 8 template <typename T> void in(T &x) {
 9     x = 0; T f = 1; char ch = getchar();
10     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
11     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
12     x *= f;
13 }
14 template <typename T> void out(T x) {
15     if(x < 0) x = -x , putchar('-');
16     if(x > 9) out(x/10);
17     putchar(x%10 + 48);
18 }
19 //---------------------------------------------------------
20 const int N = 2e5+7,inf = 1e9+7;
21 int n,k;
22 
23 struct edge {
24     int v,w,nxt;
25 }e[N<<1]; int tot,head[N];
26 
27 void add(int u,int v,int w) {
28     e[++tot].v = v; e[tot].w = w,e[tot].nxt = head[u]; head[u] = tot;
29 }
30 
31 int Tsize,rt;
32 int f[N],size[N];
33 int dis[N],dep[N];
34 
35 int t[1000007];
36 
37 bool vis[N];
38 int ans = inf;
39 
40 void get_rt(int u,int fa) {
41     size[u] = 1; f[u] = 0;
42     for(int i = head[u]; i ;i = e[i].nxt) {
43         int v = e[i].v; if(v == fa || vis[v]) continue;
44         get_rt(v,u); size[u] += size[v]; 
45         //if(f[u] < size[v]) f[u] = size[v];
46         f[u] = max(f[u],size[v]);
47     }
48     f[u] = max(f[u],Tsize-size[u]);
49     if(f[u] < f[rt]) rt = u;
50 }
51 
52 void get_ans(int u,int fa) {
53     //if(dis[u] > k) return;//> 
54     if(dis[u] <= k)
55     ans = min(ans,t[k-dis[u]]+dep[u]);
56     for(int i = head[u]; i;i = e[i].nxt) {
57         int v = e[i].v; if(v == fa || vis[v]) continue;
58         dis[v] = dis[u] + e[i].w; dep[v] = dep[u] + 1;
59         get_ans(v,u); //!!!!!未写 
60     }
61 }
62 
63 void update_t(int u,int fa,bool flag) {
64     //if(dis[u] > k) return;//>
65     if(dis[u] <= k) {
66         if(flag) t[dis[u]] = min(t[dis[u]],dep[u]);
67         else t[dis[u]] = inf;
68     }
69     for(int i = head[u]; i ;i = e[i].nxt) {
70         int v = e[i].v; if(v == fa || vis[v]) continue;
71         update_t(v,u,flag);
72     }
73 }
74 
75 void solve(int u) {
76     vis[u] = 1; t[0] = 0; //dep[u] = 0;
77     for(int i = head[u]; i; i = e[i].nxt) {
78         int v = e[i].v; if(vis[v]) continue;
79         dep[v] = 1,dis[v] = e[i].w; get_ans(v,0); update_t(v,0,1);
80     }
81     for(int i = head[u]; i; i = e[i].nxt) {
82         int v = e[i].v; if(vis[v]) continue;
83         update_t(v,0,0);
84     }
85     for(int i = head[u]; i ; i = e[i].nxt) {
86         int v = e[i].v; if(vis[v]) continue;
87         Tsize = size[v],rt = 0; get_rt(v,0); solve(rt);
88         //rt - > v
89     }
90 }
91 
92 int main() {
93     in(n); in(k); int x,y,w;
94     up(i,1,n-1) in(x),in(y),in(w),add(x+1,y+1,w),add(y+1,x+1,w);
95     up(i,0,k) t[i] = inf;
96     Tsize = n,rt = 0,f[0] = n+1; get_rt(1,0); solve(rt);
97     if(ans != inf) out(ans); else out(-1);
98     return 0;
99 }

 

转载于:https://www.cnblogs.com/mzg1805/p/10740425.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值