bzoj2599
2016-05-07 20:38
295 查看
2599: [IOI2011]Race
Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 2476 Solved: 733
[Submit][Status][Discuss]
Description
给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.Input
第一行 两个整数 n, k第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)
Output
一个整数 表示最小边数量 如果不存在这样的路径 输出-1Sample Input
4 30 1 1
1 2 2
1 3 4
Sample Output
2HINT
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
相关文章推荐
- 冒泡排序法
- 传统互联网or新兴互联网,向左or向右?
- Longest Substring with At Most Two Distinct Characters
- uva140
- CentOS 6.3中安装Gnome桌面环境
- 06 GUI(图形用户界面)
- jQuery的回调支持
- 中标麒麟在线不重启认存储
- high_memeory 映射---3
- 一台电脑上同启动两个Tomcat的方式,windows/Linux配置。
- PyCharm 设置运行参数
- 一台电脑上同启动两个Tomcat的方式,windows/Linux配置。
- CodeForces 580A Kefa and First Steps
- springMVC知识点学习笔记
- java学习总结(16.05.07) jdk的安装与环境变量的配置
- 算法的力量 ——李开复
- memcachd认识汇总
- java学习之final关键字
- VMwareWorkstation12注册机、您无权输入许可证密钥,请请使用系统管理员账户重试
- HDOJ 3507 斜率优化入门经典题