【洛谷P3128】最大流

本题当然可以用树剖解决,而且是树剖的模板题。但是对于本题来说,有一种更巧妙的办法

树上差分

类似于普通的差分,我们对于题目中的每一条路线i->j,把它拆成i->lca(i,j)->j.然后将i点、j点的权值加一,将lca(i,j)的权值减二

乍看起来没什么毛病,但是仔细想想,对lca(i,j)的子树进行前缀和,则lca(i,j)点的权值加二又减二,而题目要求lca(i,j)权值应当+1

所以我们将lca(i,j)的权值减一,将lca(i,j)的父亲的权值减一,这样就能符合题意了

差分之前预处理每个点的祖先,LCA+差分即可

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 typedef long long ll;
 5 inline int read() {
 6     int ret=0,f=1;
 7     char c=getchar();
 8     while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
 9     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
10     return ret*f;
11 }
12 using namespace std;
13 int n,k;
14 struct edge {
15     int next,to;
16 }a[50010<<1];
17 int num,head[50010<<1];
18 int sum[50010],ans;
19 int d[50010],fa[50010][31];
20 inline void add(int from,int to) {
21     a[++num].next=head[from]; a[num].to=to; head[from]=num;
22     swap(from,to);
23     a[++num].next=head[from]; a[num].to=to; head[from]=num;
24 }
25 void find(int u,int f) {
26     d[u]=d[f]+1;
27     fa[u][0]=f;
28     for(int i=0;i<30;i++) fa[u][i+1]=fa[fa[u][i]][i];
29     for(int i=head[u];i;i=a[i].next) {
30         int v=a[i].to;
31         if(v==f) continue ;
32         find(v,u);
33     }
34 }
35 int lca(int x,int y) {
36     if(d[x]<d[y]) swap(x,y);
37     for(int i=30;i>=0;i--) {
38         if(d[fa[x][i]]>=d[y]) x=fa[x][i];
39         if(x==y) return x;
40     }
41     for(int i=30;i>=0;i--)    
42         if(fa[x][i]!=fa[y][i]) {
43             x=fa[x][i];
44             y=fa[y][i];
45         }
46     return fa[x][0];
47 }
48 void dfs(int u,int f) {
49     for(int i=head[u];i;i=a[i].next) {
50         int v=a[i].to;
51         if(v==f) continue ;
52         dfs(v,u);
53         sum[u]+=sum[v];
54     }
55     ans=max(ans,sum[u]);
56 }
57 int main() {
58     n=read(); k=read();
59     for(int i=1;i<n;i++) add(read(),read());
60     find(1,0);
61     for(int i=1;i<=k;i++) {
62         int x=read(),y=read();
63         sum[x]++;
64         sum[y]++;
65         int ret=lca(x,y);
66         sum[ret]--;
67         sum[fa[ret][0]]--; 
68     }
69     dfs(1,0);
70     printf("%d\n",ans);
71     return 0;
72 }
AC Code

 

posted @ 2019-03-16 19:48  AD_shl  阅读(265)  评论(0编辑  收藏  举报