您的位置:首页 > 其它

bzoj2599

2016-05-07 20:38 295 查看

2599: [IOI2011]Race

Time Limit: 70 Sec Memory Limit: 128 MB
Submit: 2476 Solved: 733
[Submit][Status][Discuss]

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

HINT

Source

题解:
  随便点分治,用一个ans[i]代表u,v距离为k,边数为i的点对个数,那么答案就为i (ans[i]>0 && i 最小);
  怎么求ans? 自己yy一下吧
代码:
  

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define N 200100
using namespace std;
int tot,n,m,all,k,root,sum;
int pre[N*2],v[N*2],val[N*2],now
,size
,ans
,f
;
bool vis
;
struct data{int val,size;
}d
,da
;
bool cmp(data a,data b)
{
return a.val<b.val;
}
int read()
{
int x=0; char ch; bool bo=1;
while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=0;
while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
if (!bo) return -x; return x;
}
void ins(int a,int b,int c)
{
++tot; pre[tot]=now[a]; now[a]=tot; v[tot]=b; val[tot]=c;
}
void getroot(int u,int fa)
{
size[u]=1; f[u]=0;
for (int p=now[u]; p; p=pre[p])
{
int son=v[p];
if (vis[son]||son==fa) continue;
getroot(son,u);
size[u]+=size[son];
f[u]=max(f[u],size[son]);
}
f[u]=max(f[u],all-size[u]);
if (f[u]<f[root]) root=u;
}
void getarray(int u,int fa)
{
for (int p=now[u]; p; p=pre[p])
{
int son=v[p];
if (son==fa||vis[son]) continue;
da[++sum].val=d[son].val=d[u].val+val[p];
da[sum].size=d[son].size=d[u].size+1;
getarray(son,u);
}

}
void calc(int u,int value, int f)
{
d[u].val=value; if (f==1) d[u].size=0; else d[u].size=1;
sum=0; da[++sum].val=value; da[sum].size=d[u].size;
getarray(u,0);
sort(da+1,da+1+sum,cmp);
for (int i=1,j=sum; i<=j; i++)
{
while (j>i && da[j].val+da[i].val>k) j--;
for (int p=j; da[i].val+da[p].val==k ;p--)ans[da[p].size+da[i].size]+=f;
}
}
void solve(int u)
{
vis[u]=1; calc(u,0,1);
for    (int p=now[u]; p; p=pre[p])
{
int son=v[p];
if (vis[son]) continue;
calc(son,val[p],-1);
all=size[son];
root=0; getroot(son,0);
solve(root);
}
}
int main()
{
n=read(); k=read();
for (int i=1; i<n; i++)
{
int u=read()+1,v=read()+1,value=read();
ins(u,v,value); ins(v,u,value);
}
all=n; f[root=0]=n; getroot(1,0);
solve(root);
for (int i=1; i<n; i++)
{
if (ans[i])
{
printf("%d\n",i);
return 0;
}
}
printf("-1\n"); return 0;
}


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