BZOJ 2599 Race(树分治)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2599
题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小.
题意:每次找到当前树的重心作为树根,查找通过当前树根的路径。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #include<ctime> 7 int tot,go[1000005],next[1000005],first[1000005],val[1000005]; 8 int size[1000005],F[1000005],cnt[1000005],a[1000005],root,n,K,vis[1000005]; 9 int dis[1000005],ans,sz,h[1000005],sum; 10 long long sx; 11 int read(){ 12 char ch=getchar();int t=0,f=1; 13 while (ch<'0'||ch>'9') { 14 if (ch=='-') f=-1; 15 ch=getchar(); 16 } 17 while ('0'<=ch&&ch<='9'){ 18 t=t*10+ch-'0'; 19 ch=getchar(); 20 } 21 return t*f; 22 } 23 void insert(int x,int y,int z){ 24 tot++; 25 go[tot]=y; 26 next[tot]=first[x]; 27 first[x]=tot; 28 val[tot]=z; 29 } 30 void add(int x,int y,int z){ 31 insert(x,y,z); 32 insert(y,x,z); 33 } 34 void findroot(int x,int fa){ 35 size[x]=1;F[x]=0; 36 for (int i=first[x];i;i=next[i]){ 37 int pur=go[i]; 38 if (pur==fa||vis[pur]) continue; 39 findroot(pur,x); 40 size[x]+=size[pur]; 41 F[x]=std::max(F[x],size[pur]); 42 } 43 F[x]=std::max(F[x],sum-size[x]); 44 if (F[root]>F[x]) root=x; 45 } 46 void dfs1(int x,int fa){ 47 sx++; 48 if (dis[x]>K) return; 49 if (h[K-dis[x]]==sz) ans=std::min(ans,a[K-dis[x]]+cnt[x]); 50 for (int i=first[x];i;i=next[i]){ 51 int pur=go[i]; 52 if (pur==fa||vis[pur]) continue; 53 cnt[pur]=cnt[x]+1; 54 dis[pur]=dis[x]+val[i]; 55 dfs1(pur,x); 56 } 57 } 58 void dfs2(int x,int fa){ 59 if (dis[x]>K) return; 60 if (h[dis[x]]!=sz) h[dis[x]]=sz,a[dis[x]]=cnt[x]; 61 else a[dis[x]]=std::min(a[dis[x]],cnt[x]); 62 for (int i=first[x];i;i=next[i]){ 63 int pur=go[i]; 64 if (pur==fa||vis[pur]) continue; 65 dfs2(pur,x); 66 } 67 } 68 int find(int x,int fa){ 69 int all=1; 70 for (int i=first[x];i;i=next[i]){ 71 int pur=go[i]; 72 if (pur==fa||vis[pur]) continue; 73 all+=find(pur,x); 74 } 75 return all; 76 } 77 void query(int x){ 78 h[0]=++sz; 79 a[0]=0; 80 vis[x]=1; 81 for (int i=first[x];i;i=next[i]){ 82 int pur=go[i]; 83 if (vis[pur]) continue; 84 dis[pur]=val[i]; 85 cnt[pur]=1; 86 dfs1(pur,x); 87 dfs2(pur,x); 88 } 89 for (int i=first[x];i;i=next[i]){ 90 int pur=go[i]; 91 if (vis[pur]) continue; 92 root=0; 93 sum=find(pur,0); 94 findroot(pur,0); 95 query(root); 96 } 97 } 98 int main(){ 99 n=read();K=read(); 100 for (int i=1;i<n;i++){ 101 int x,y,z; 102 x=read(); 103 y=read(); 104 z=read(); 105 x++;y++; 106 add(x,y,z); 107 } 108 root=0; 109 F[0]=n+1; 110 ans=n; 111 sum=n; 112 findroot(1,0); 113 query(root); 114 if (ans==n) ans=-1; 115 printf("%d\n",ans); 116 }