【BZOJ2599】Race(点分治)

题意:给一棵树,每条边有权.求一条简单路径,权值和等于K,且边的数量最小.

N <= 200000, K <= 1000000

思路:跟着高中学长李日天(迪克李)的课件复习一下树分治

https://wenku.baidu.com/view/ae220cc0ed630b1c58eeb5b3.html

也算是自己第一道独立完成的点分治,纪念一下

From https://www.cnblogs.com/candy99/p/6270581.html

小总结:

目前遇到的点分治处理有两种:

1.先统计每颗子树,处理一颗子树时使用了之前子树的信息
2.先统计整棵树然后减去同一棵子树里的,可以只一遍邻接链表循环

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<string>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<map>
  8 #include<set>
  9 #include<queue>
 10 #include<vector>
 11 using namespace std;
 12 typedef long long ll;
 13 typedef unsigned int uint;
 14 typedef unsigned long long ull;
 15 typedef pair<int,int> PII;
 16 typedef vector<int> VI;
 17 #define fi first
 18 #define se second s
 19 #define MP make_pair
 20 #define N   410000
 21 #define M   1100000
 22 #define MOD 1000000007
 23 #define eps 1e-8 
 24 #define pi acos(-1)
 25 #define oo 1e9
 26 
 27 int q[N][2],head[N],vet[N],nxt[N],len[N],dis[N],dep[N],flag[N],son[N],c[N],
 28     f[M],n,tot,top,ans,sum,root,K;
 29 
 30 
 31 
 32 int read()
 33 { 
 34    int v=0,f=1;
 35    char c=getchar();
 36    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 37    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 38    return v*f;
 39 }
 40 
 41 void add(int a,int b,int c)
 42 {
 43     nxt[++tot]=head[a];
 44     vet[tot]=b;
 45     len[tot]=c;
 46     head[a]=tot;
 47 }
 48 
 49 void getroot(int u,int fa)
 50 {
 51     son[u]=1; c[u]=0;
 52     int e=head[u];
 53     while(e)
 54     {
 55         int v=vet[e];
 56         if(v!=fa&&!flag[v])
 57         {
 58             getroot(v,u);
 59             son[u]+=son[v];
 60             c[u]=max(c[u],son[v]);
 61         }
 62         e=nxt[e];
 63     }
 64     c[u]=max(c[u],sum-c[u]);
 65     if(c[u]<c[root]) root=u;
 66 }
 67 
 68 void dfs(int u,int fa)
 69 {
 70     q[++top][1]=dis[u];
 71     q[top][2]=dep[u];
 72     int e=head[u];
 73     while(e)
 74     {
 75         int v=vet[e];
 76         if(v!=fa&&!flag[v])
 77         {
 78             dep[v]=dep[u]+1;
 79             dis[v]=dis[u]+len[e];
 80             dfs(v,u);
 81         }
 82         e=nxt[e];
 83     }
 84 }
 85 
 86 void work(int u)
 87 {
 88     flag[u]=1; f[0]=0; dep[u]=1;
 89     int e=head[u];
 90     while(e)
 91     {
 92         int v=vet[e];
 93         if(!flag[v])
 94         {
 95             top=0; 
 96             dis[v]=len[e]; 
 97             dep[v]=1;
 98             dfs(v,u);
 99             for(int i=1;i<=top;i++)
100             { 
101                 int t=K-q[i][1];
102                 if(t>=0&&t<=K) ans=min(ans,q[i][2]+f[t]);
103             }
104             ans=min(ans,f[K]);
105             for(int i=1;i<=top;i++) 
106              if(q[i][1]>=0&&q[i][1]<=K) f[q[i][1]]=min(f[q[i][1]],q[i][2]);
107         }
108         e=nxt[e];    
109     }
110     
111     e=head[u];
112     while(e)
113     {
114         int v=vet[e];
115         if(!flag[v])
116         {
117             top=0; 
118             dis[v]=len[e]; 
119             dep[v]=1;
120             dfs(v,u);
121             for(int i=1;i<=top;i++) 
122              if(q[i][1]>=0&&q[i][1]<=K) f[q[i][1]]=oo;
123         }
124         e=nxt[e];    
125     }
126 
127     e=head[u];
128     while(e)
129     {
130         int v=vet[e];
131         if(!flag[v])
132         {
133             sum=son[v]; root=0;
134             getroot(v,0);
135             work(root);
136         }
137         e=nxt[e];
138     }
139 }
140 
141 int main()
142 {
143     //freopen("bzoj2599.in","r",stdin);
144     //freopen("bzoj2599.out","w",stdout);
145     scanf("%d%d",&n,&K);
146     for(int i=1;i<=n-1;i++)
147     {
148         int x,y,z;
149         scanf("%d%d%d",&x,&y,&z);
150         x++; y++;
151         add(x,y,z);
152         add(y,x,z);
153     }
154     root=0; sum=n; c[0]=n; 
155     ans=oo;
156     for(int i=0;i<=K;i++) f[i]=oo;
157     getroot(1,0);
158     work(root);
159     if(ans>n) printf("-1\n");
160      else printf("%d\n",ans);
161     return 0;
162 }
163     
164     
165 
166 
167             
168         

猜你喜欢

转载自www.cnblogs.com/myx12345/p/9710738.html