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。。
明显点分治,但是愚蠢的我并没有想到怎么分治。。%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; }
相关文章推荐
- 【BZOJ 2599】 [IOI2011]Race 树的点分治
- 【bzoj2599】[IOI2011]Race 树的点分治
- BZOJ2599 [IOI2011]Race 【点分治】
- [BZOJ2599][IOI2011]Race(点分治)
- 点分治[BZOJ]2599: [IOI2011]Race
- [BZOJ2599][Race][IOI2011]点分治
- bzoj 2599: [IOI2011]Race 点分治
- BZOJ 2599 [IOI2011]Race【Tree,点分治】
- BZOJ 2599: [IOI2011]Race( 点分治 )
- BZOJ 2599 IOI2011 Race 树的点分治
- BZOJ 2599 [IOI2011]Race【Tree,点分治】
- 【BZOJ2599】[IOI2011]Race 树的点分治
- [树的点分治] [树形DP] [BZOJ2599] [IOI2011] Race
- BZOJ 2599 IOI 2011 Race 树的分治
- BZOJ 2599: [IOI2011]Race 点分治题解
- bzoj2599 [IOI2011]Race(点分治)
- 【点分治】BZOJ 2599:[IOI2011]Race
- BZOJ 2599: [IOI2011]Race [点分治]
- 【BZOJ2599】[IOI2011]Race【点分治】
- 【BZOJ】2599 [IOI2011]Race 点分治