bzoj 2599 [IOI2011]Race
2017-05-23 10:08
267 查看
2599: [IOI2011]Race
Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 3590 Solved: 1059
[Submit][Status][Discuss]
Description
给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000Input
第一行 两个整数 n, k第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)
Output
一个整数 表示最小边数量 如果不存在这样的路径 输出-1Sample Input
4 30 1 1
1 2 2
1 3 4
Sample Output
2HINT
Source
【分析】树的点分治
t[i]表示长度为i的路径最少有多少条边,分治的同时更新t数组和计算答案。注意这里要一边更新t数组一边计算答案。
每次初始化不能用memset,否则会TLE,可以按照DFS的顺序依次将更新的值恢复原值。
【代码】
//bzoj 2599 Race #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define inf 1e9+7 #define ll long long #define M(a) memset(a,0,sizeof a) #define fo(i,j,k) for(i=j;i<=k;i++) using namespace std; const int mxn=1000005; bool vis[mxn]; int n,m,T,mn,cnt,ans,num,root; struct edge {int to,w,next;} f[mxn<<1]; int head[mxn],dis[mxn],size[mxn],mx[mxn],dep[mxn],t[mxn]; inline void add(int u,int v,int w) { f[++cnt].to=v,f[cnt].w=w,f[cnt].next=head[u],head[u]=cnt; } inline void dfssize(int u,int fa) { size[u]=1,mx[u]=0; for(int i=head[u];i;i=f[i].next) { int v=f[i].to; if(vis[v] || v==fa) continue; dfssize(v,u); size[u]+=size[v]; mx[u]=max(mx[u],size[v]); } } inline void dfsroot(int r,int u,int fa) { mx[u]=max(mx[u],size[r]-size[u]); if(mx[u]<mn) mn=mx[u],root=u; for(int i=head[u];i;i=f[i].next) { int v=f[i].to; if(vis[v] || v==fa) continue; dfsroot(r,v,u); } } inline void calc(int u,int fa) { if(dis[u]<=m) ans=min(ans,dep[u]+t[m-dis[u]]); for(int i=head[u];i;i=f[i].next) { int v=f[i].to; if(vis[v] || v==fa) continue; dep[v]=dep[u]+1,dis[v]=dis[u]+f[i].w,calc(v,u); } } inline void update(int u,int fa) { if(dis[u]<=m) t[dis[u]]=min(t[dis[u]],dep[u]); for(int i=head[u];i;i=f[i].next) { int v=f[i].to; if(vis[v] || v==fa) continue; update(v,u); } } inline void erase(int u,int fa) { if(dis[u]<=m) t[dis[u]]=inf; for(int i=head[u];i;i=f[i].next) { int v=f[i].to; if(vis[v] || v==fa) continue; erase(v,u); } } inline void dfs(int u) { mn=n; dfssize(u,0); dfsroot(u,u,0); vis[root]=1,t[0]=0; for(int i=head[root];i;i=f[i].next) { int v=f[i].to; if(vis[v]) continue; dep[v]=1,dis[v]=f[i].w; calc(v,root),update(v,root); } for(int i=head[root];i;i=f[i].next) { int v=f[i].to; if(vis[v]) continue; erase(v,root); } for(int i=head[root];i;i=f[i].next) { int v=f[i].to; if(vis[v]) continue; dfs(v); } } int main() { int i,j,k,u,v,w; scanf("%d%d",&n,&m); fo(i,1,m) t[i]=inf; fo(i,2,n) { scanf("%d%d%d",&u,&v,&w); add(u+1,v+1,w),add(v+1,u+1,w); } ans=n; dfs(1); printf("%d\n",ans==n?-1:ans); return 0; }
相关文章推荐
- BZOJ 2599 [IOI2011]Race【Tree,点分治】
- bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race
- [树的点分治] [树形DP] [BZOJ2599] [IOI2011] Race
- BZOJ2599: [IOI2011]Race
- bzoj2599: [IOI2011]Race
- BZOJ2599 [IOI2011]Race 【点分治】
- 【BZOJ2599】[IOI2011]Race【点分治】
- [BZOJ2599][IOI2011]Race(点分治)
- BZOJ 2599: [IOI2011]Race( 点分治 )
- bzoj2599 [IOI2011]Race
- bzoj 2599: [IOI2011]Race(树的点分治)
- BZOJ2599 - [IOI2011]Race
- [BZOJ2599][IOI2011]Race 点分治
- Bzoj 2599: [IOI2011]Race(点分治)
- BZOJ2599: [IOI2011]Race
- BZOJ2599: [IOI2011]Race
- bzoj 2599: [IOI2011]Race (点分治)
- Bzoj2599:[IOI2011]Race:树的点分治
- BZOJ 2599 IOI 2011 Race 点分治
- 【BZOJ 2599】 [IOI2011]Race 树的点分治