zoukankan      html  css  js  c++  java
  • 【洛谷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
    ",ans);
    71     return 0;
    72 }
    AC Code
  • 相关阅读:
    Python读excel——xlrd
    markdown demo 学习
    Markdown 语法介绍
    安全学习概览——恶意软件分析、web渗透、漏洞利用和挖掘、内网渗透、IoT安全分析、区块链、黑灰产对抗
    诺基亚 IoT安全白皮书
    北京Uber优步司机奖励政策(4月17日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(4月17日)
    百度、腾讯和阿里内部的级别和薪资待遇是什么样的?
    成都Uber优步司机奖励政策(4月16日)
    北京Uber优步司机奖励政策(4月16日)
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10544014.html
Copyright © 2011-2022 走看看