bzoj2599
2016-08-15 09:58
411 查看
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; 949a } } printf("-1\n"); return 0; }
View Code
相关文章推荐
- bzoj2152
- bzoj1468
- bzoj2588
- 压缩图片
- KeyBoardUtils.java——android键盘工具类
- bzoj3123
- bzoj3932
- bzoj1901
- bzoj3551
- 2782: [HNOI2006]最短母串
- 用grunt搭建自动化的web前端开发环境-完整教程
- 【自学笔记】简单java电话本管理系统v2.0源码
- Poi2006 Palindromes
- Android中使用Socket来实现服务器端和客户端,进行数据通信(使用原生Socket)
- 2786: [JSOI]Word Query电子字典
- 2781: [JSOI2007]文本生成器
- 这些时间投,更容易被HR“翻牌子”!
- [NOI2011]阿狸的打字机(好题!!!!)
- [TJOI2013]单词
- [Usaco2008 Dec]Secret Message 秘密信息