BZOJ2599 [IOI2011]Race 点分治
2018-02-08 15:15
369 查看
Problem
洛谷链接BZOJ链接
没错bzoj的就是个假链接,貌似是权限题啊……苦逼 _ (:з」∠) _还是洛谷友善啊
Solution
给一棵树,每条边有权。求一条简单路径,权值和等于 K ,且边的数量最小。为了方便更新答案,考虑设置辅助数组t[i],用于记录在当前的子树中,走到距离为i的节点至少要经过几条边。
然后在getdis的时候顺便更新一下答案就好了。
Code
#include <iostream> #include <cstdio> using namespace std; const int maxn=200010,INF=0x3f3f3f3f; struct data{ int v,w,nxt; }edge[maxn<<1]; int n,k,p,rt,sum,ans,head[maxn]; int f[maxn],vis[maxn],sz[maxn],dis[maxn],d[maxn],t[1000010]; template <typename Tp> inline void read(Tp &x) { x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } inline int max(int x,int y){return x>y?x:y;} inline int min(int x,int y){return x<y?x:y;} inline void insert(int u,int v,int w) { edge[++p]=(data){v,w,head[u]};head[u]=p; edge[++p]=(data){u,w,head[v]};head[v]=p; } void input() { int u,v,w; read(n);read(k); for(int i=1;i<=k;i++) t[i]=n; for(int i=1;i<n;i++) read(u),read(v),read(w),insert(u+1,v+1,w); } void getrt(int x,int pre) { sz[x]=1;f[x]=0; for(int i=head[x];i;i=edge[i].nxt) if(edge[i].v!=pre&&!vis[edge[i].v]) getrt(edge[i].v,x),sz[x]+=sz[edge[i].v],f[x]=max(f[x],sz[edge[i].v]); f[x]=max(f[x],sum-sz[x]); if(f[rt]>f[x]) rt=x; } void getdis(int x,int pre) { if(dis[x]<=k) ans=min(ans,d[x]+t[k-dis[x]]); for(int i=head[x];i;i=edge[i].nxt) if(edge[i].v!=pre&&!vis[edge[i].v]) { d[edge[i].v]=d[x]+1; dis[edge[i].v]=dis[x]+edge[i].w; getdis(edge[i].v,x); } } void calc(int x,int pre,int 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=edge[i].nxt) if(edge[i].v!=pre&&!vis[edge[i].v]) calc(edge[i].v,x,flag); } void dfs(int x) { vis[x]=1;t[0]=0; for(int i=head[x];i;i=edge[i].nxt) if(!vis[edge[i].v]) { d[edge[i].v]=1;dis[edge[i].v]=edge[i].w; getdis(edge[i].v,0);calc(edge[i].v,0,1); } for(int i=head[x];i;i=edge[i].nxt) if(!vis[edge[i].v]) calc(edge[i].v,0,0);//重置t数组 for(int i=head[x];i;i=edge[i].nxt) if(!vis[edge[i].v]) { sum=sz[edge[i].v];rt=0; getrt(edge[i].v,0); dfs(rt); } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif input(); sum=ans=f[0]=n; getrt(1,0);dfs(rt); if(ans==n) puts("-1"); else printf("%d\n",ans); return 0; }
相关文章推荐
- BZOJ 2599: [IOI2011]Race 点分治
- 【BZOJ】2599 [IOI2011]Race 点分治
- BZOJ 2599 IOI 2011 Race 点分治
- 【BZOJ2599】[IOI2011]Race【点分治】
- BZOJ 2599 IOI2011 Race 树的点分治
- bzoj 2599: [IOI2011]Race(树的点分治)
- BZOJ2599 [IOI2011] [Race] 点分治
- bzoj 2599: [IOI2011]Race (点分治)
- 【BZOJ 2599】【IOI 2011】Race 点分治
- [BZOJ2599][IOI2011]Race 点分治
- BZOJ.2599.[IOI2011]Race(点分治)
- BZOJ 2599 IOI 2011 Race 树的分治
- [BZOJ2599][IOI2011]Race(点分治)
- bzoj 2599 [IOI2011]Race (点分治)
- bzoj2599: [IOI2011]Race 点分治
- 【BZOJ 2599】 [IOI2011]Race 树的点分治
- Bzoj2599:[IOI2011]Race:树的点分治
- BZOJ2599 [IOI2011]Race 【点分治】
- 【bzoj2599】[IOI2011]Race 树的点分治
- BZOJ2599 [IOI2011]Race 【点分治】