bzoj 2599 [IOI2011]Race 点分
[IOI2011]Race
Time Limit: 70 Sec Memory Limit: 128 MBSubmit: 4768 Solved: 1393
[Submit][Status][Discuss]
Description
给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.N <= 200000, K <= 1000000
Input
第一行 两个整数 n, k
第二..n行 每行三个整数 表示一条无向边的两端和权值 (注意点的编号从0开始)
Output
一个整数 表示最小边数量 如果不存在这样的路径 输出-1
Sample Input
4 3
0 1 1
1 2 2
1 3 4
0 1 1
1 2 2
1 3 4
Sample Output
2
HINT
2018.1.3新加数据一组,未重测
点分治模板题
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 9 #define ll long long 10 #define inf 1000000007 11 #define N 200007 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 17 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 21 int num=0; 22 int n,k; 23 int total,id,f[N],siz[N]; 24 ll tot,a[N]; 25 int bs[N]; 26 int ans=inf; 27 bool vis[N]; 28 int cnt,hed[N],rea[N<<1],nxt[N<<1],val[N<<1]; 29 map<ll,int>p; 30 31 void add(int u,int v,int z) 32 { 33 nxt[++cnt]=hed[u]; 34 hed[u]=cnt; 35 rea[cnt]=v; 36 val[cnt]=z; 37 } 38 void add_two_way(int x,int y,int z) 39 { 40 add(x,y,z); 41 add(y,x,z); 42 } 43 void get_heart(int u,int fa) 44 { 45 siz[u]=1,f[u]=0; 46 for (int i=hed[u];i!=-1;i=nxt[i]) 47 { 48 int v=rea[i]; 49 if (v==fa||vis[v]) continue; 50 get_heart(v,u); 51 siz[u]+=siz[v],f[u]=max(f[u],siz[v]); 52 } 53 f[u]=max(f[u],total-siz[u]); 54 if (f[u]<f[id]) id=u; 55 } 56 void dfs(int u,int fa) 57 { 58 int now=tot; 59 if (a[tot]==k) ans=min(ans,bs[tot]); 60 if (p[k-a[tot]]) ans=min(ans,p[k-a[tot]]+bs[tot]); 61 for (int i=hed[u];i!=-1;i=nxt[i]) 62 { 63 int v=rea[i],fee=val[i]; 64 if (fa==v||vis[v]) continue; 65 bs[++tot]=bs[now]+1,a[tot]=a[now]+fee; 66 dfs(v,u); 67 } 68 } 69 void calc(int u) 70 { 71 map<ll,int>z; 72 swap(p,z),bs[u]=0; 73 for (int i=hed[u];i!=-1;i=nxt[i]) 74 { 75 int v=rea[i],fee=val[i]; 76 if (vis[v]) continue; 77 bs[++tot]=1,a[tot]=fee; 78 dfs(v,u); 79 for (int i=1;i<=tot;i++) 80 if (!p[a[i]]) p[a[i]]=bs[i]; 81 else p[a[i]]=min(p[a[i]],bs[i]); 82 tot=0; 83 } 84 } 85 void solve(int u) 86 { 87 vis[u]=true;calc(u);int sum=total; 88 for (int i=hed[u];i!=-1;i=nxt[i]) 89 { 90 int v=rea[i]; 91 if (vis[v]) continue; 92 total=(siz[v]>siz[u])?sum-siz[u]:siz[v]; 93 id=0,get_heart(v,u); 94 solve(id); 95 } 96 } 97 int main() 98 { 99 freopen("fzy.in","r",stdin); 100 // freopen("fzy.out","w",stdout); 101 102 memset(hed,-1,sizeof(hed)); 103 n=read(),k=read(); 104 for (int i=1;i<n;i++) 105 { 106 int x=read(),y=read(),z=read();x++,y++; 107 add_two_way(x,y,z); 108 } 109 total=f[0]=n; 110 get_heart(1,0); 111 solve(id); 112 if (ans==inf) puts("-1"); 113 else printf("%d\n",ans); 114 }