您的位置:首页 > 其它

2599: [IOI2011]Race

2018-06-02 18:04 232 查看

2599: [IOI2011]Race

链接

分析

  被memset卡。。。

  点分治,对于重心,遍历子树,记录一个数组T[i],表示以重心为起点的长度为i的路径中最少的边数是多少。然后先遍历子树,更新答案,然后在遍历一边更新T,防止出现两个起点在同一棵子树中的情况。

 

代码

#include<cstdio>
#include<algorithm>
#include<cctype>

using namespace std;

const int N = 200100;
const int INF = 1e9;

struct Edge{
int to,nxt,w;
Edge() {}
Edge(int a,int b,int c) {to = a,w = b,nxt = c;}
}e[N<<1];
int head
,siz
,T[1000010];
bool vis
;
int n,k,tot,Size,Num,Root,Ans = N;

inline int read() {
int x = 0,f = 1;char ch=getchar();
for (; !isdigit(ch); ch=getchar()) if(ch=='-')f=-1;
for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
return x*f;
}
void add_edge(int u,int v,int w) {
e[++tot] = Edge(v,w,head[u]);head[u] = tot;
e[++tot] = Edge(u,w,head[v]);head[v] = tot;
}
void getRoot(int u,int fa) {
siz[u] = 1;
int mx = 0;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (v == fa || vis[v]) continue;
getRoot(v,u);
siz[u] += siz[v];
mx = max(siz[v],mx);
}
mx = max(Size-siz[u],mx);
if (mx < Num) Root = u,Num = mx;
}
void dfs1(int u,int fa,int L,int C) {
if (L > k) return ;
Ans = min(Ans,T[k-L]+C);
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (v == fa || vis[v]) continue;
dfs1(v,u,L+e[i].w,C+1);
}
}
void dfs2(int u,int fa,int L,int C,int f) {
if (L > k) return ;
if (f) T[L] = min(T[L],C);
else T[L] = INF;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (v == fa || vis[v]) continue;
dfs2(v,u,L+e[i].w,C+1,f);
}
}
void calcc(int u) {
T[0] = 0;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (vis[v]) continue;
dfs1(v,u,e[i].w,1);
dfs2(v,u,e[i].w,1,1);
}
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (vis[v]) continue;
dfs2(v,u,e[i].w,1,0);
}
}
void solve(int u) {
vis[u] = true;
calcc(u);
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (vis[v]) continue;
Size = siz[v],Root = 0,Num = 1e9;
getRoot(v,0);
solve(Root);
}
}
int main() {
n = read(),k = read();
for (int i=1; i<=k; ++i) T[i] = INF;
for (int u,v,w,i=1; i<n; ++i) {
u = read(),v = read(),w = read();
add_edge(u+1,v+1,w);
if (w == k) {printf("-1");return 0;}
}
Size = n;Num = 1e9;
getRoot(1,0);
solve(Root);
if (Ans == N) puts("-1");
else printf("%d",Ans);
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: