您的位置:首页 > 其它

bzoj2599: [IOI2011]Race 点分治

2017-04-22 11:18 295 查看
题意:给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000

明显点分治,但是愚蠢的我并没有想到怎么分治。。%hzwer。

开一个t[i]表示整棵树中权值和为i的路径有多少条,那么我们分治每一颗树的时候,再算出子节点到当前根的dis[x]权值距离和d[x]点数距离,然后就可以直接更新了ans=min(ans,t[k-dis[x]]+d[x]);

然后再更新dis和d,因为如果先更新了就会算重,有一种情况,即起点终点在子树内但是经过了根,这样就会算重复了。。

注意inf设小一点,不然会爆int。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=4e5+5;
const int M=1e6+5;
int n,m;
const int inf=0x7fffffff/3;
int cnt,sum,root,ans,k;
int t[M],head
,next
,go
,val
;
int dis
,d
,son
,f
,tot;
bool vis
;
inline void add(int x,int y,int z)
{
go[++tot]=y;
val[tot]=z;
next[tot]=head[x];
head[x]=tot;
}
inline void getroot(int x,int fa)
{
son[x]=1;
f[x]=0;
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (!vis[v]&&v!=fa)
{
getroot(v,x);
son[x]+=son[v];
f[x]=max(f[x],son[v]);
}
}
f[x]=max(f[x],sum-son[x]);
if (f[x]<f[root])root=x;
}
inline void cal(int x,int fa)
{
if (dis[x]<=k)ans=min(ans,d[x]+t[k-dis[x]]);
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (v!=fa&&!vis[v])
{
d[v]=d[x]+1;
dis[v]=dis[x]+val[i];
cal(v,x);
}
}
}
inline void update(int x,int fa,bool flag)
{
if (dis[x]<=k)
{
if (flag)t[dis[x]]=min(t[dis[x]],d[x]);
else t[dis[x]]=inf;
}
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (v!=fa&&!vis[v])update(v,x,flag);
}
}
inline void work(int x)
{
vis[x]=1;
t[0]=0;
for(int i=head[x];i;i=next[i])
{
int v=go[i];
if (!vis[v])
{
d[v]=1;
dis[v]=val[i];
cal(v,0);
update(v,0,1);
}
}
for(int i=head[x];i;i=next[i])
if (!vis[go[i]])update(go[i],0,0);
for(int i=head[x];i;i=next[i])
if (!vis[go[i]])
{
int v=go[i];
root=0;
sum=son[v];
getroot(v,0);
work(root);
}
}
int main()
{
scanf("%d%d",&n,&k);
fo(i,1,k)t[i]=inf/3;
fo(i,1,n-1)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
x++,y++;
add(x,y,z);
add(y,x,z);
}
ans=sum=f[0]=n;
getroot(1,0);
work(root);
if (ans!=n)printf("%d\n",ans);
else printf("-1\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: