您的位置:首页 > 其它

bzoj2599 [IOI2011]Race

2014-12-08 10:30 162 查看

Description

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

Input

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

Output

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

Sample Input

4 3

0 1 1

1 2 2

1 3 4

Sample Output

2

第一次写点分治……要讲详细点
把所有可行解分成过当前点和不过当前点两种情况,过当前点的直接处理,不过当前点的就递归到子树做,然后一样分为过当前点和不过当前点……
然后要找个树的重心,就是把无根树建成以x为根的有根树之后,使子树的儿子个数最大值最小的x
对于这题,用t[k]表示当前子树中到根的路径权值和为k的最短边。换而言之就是权值和为k又经过最少边
然后就可以分治搞掉

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define LL long long
#define inf 0x7ffffff
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
#define N 200010
using namespace std;
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,k,cnt,sum,root,ans;
struct edge{
int to,next,v;
}e[2*N];
int head
;
int f
;
int son
;
int vis
;
int dep
;
int dist
;
int t[1000010];
inline void ins(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].v=w;
e[cnt].next=head[u];
head[u]=cnt;
}
inline void insert(int u,int v,int w)
{
ins(u,v,w);
ins(v,u,w);
}
inline void getroot(int x,int fa)
{
son[x]=1;f[x]=0;
for (int i=head[x];i;i=e[i].next)
if (e[i].to!=fa&&!vis[e[i].to])
{
getroot(e[i].to,x);
son[x]+=son[e[i].to];
f[x]=max(f[x],son[e[i].to]);
}
f[x]=max(f[x],sum-son[x]);
if (f[x]<f[root])root=x;
}
inline void dfs(int x,int fa)
{
if(dist[x]<=k)ans=min(ans,dep[x]+t[k-dist[x]]);
for (int i=head[x];i;i=e[i].next)
if (fa!=e[i].to&&!vis[e[i].to])
{
dep[e[i].to]=dep[x]+1;
dist[e[i].to]=dist[x]+e[i].v;
dfs(e[i].to,x);
}
}
inline void add(int x,int fa,int opr)
{
if (dist[x]<=k)
{
if (opr==1)t[dist[x]]=min(t[dist[x]],dep[x]);
else t[dist[x]]=inf;
}
for (int i=head[x];i;i=e[i].next)
if (e[i].to!=fa&&!vis[e[i].to])
add(e[i].to,x,opr);
}
inline void work(int x)
{
vis[x]=1;t[0]=0;
for (int i=head[x];i;i=e[i].next)
if (!vis[e[i].to])
{
dep[e[i].to]=1;dist[e[i].to]=e[i].v;
dfs(e[i].to,0);
add(e[i].to,0,1);
}
for (int i=head[x];i;i=e[i].next)
if (!vis[e[i].to])add(e[i].to,0,0);
for (int i=head[x];i;i=e[i].next)
if (!vis[e[i].to])
{
root=0;sum=son[e[i].to];
getroot(e[i].to,0);
work(root);
}
}
int main()
{
n=read();k=read();
for (int i=1;i<=k;i++)t[i]=n;
for(int i=1;i<n;i++)
{
int x=read()+1,y=read()+1,z=read();
insert(x,y,z);
}
ans=sum=f[0]=n;
getroot(1,0);
work(root);
if (ans==n)printf("-1\n");
else printf("%d\n",ans);
return 0;
}


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