题意:给出一棵树,边上有容量限制,求以任一点作为根和源点,叶子作为汇点的最大流的最大值

首先上网络流等于找死

树形DP可以\(O(n)\)求出以某点\(u\)为根的最大流,只需设\(f[u]=\sum min(cap_{u→v},f[v])\),

这是一个自底向上的过程

其中存在\(min\)是因为\(f[v]\)不包含连向\(u\)的边,要保证合法增广,

注意如果\(v\)为叶子则直接加上\(cap_{u→v}\)

此时我们也得知\(f[v]\)是以v为根的子树的最大流

那么换根后显然以\(v\)为整棵树的根时,最大流\(g[v]\)至少包含\(f[v]\),还有指向父亲\(u\)部分的贡献,这部分的贡献有原式可以比较得出为\(min(cap_{u→v},g[u]-min(cap_{u→v},f[v]))\),同理叶子需要特判,且\(f[root]=g[root]\)

这是一个自顶向下的过程

由此只需\(O(n)\)扫两遍就能得出任一点作为源点的最大流

另外由于POJ过于垃圾请交C++

PS.换根对于贡献的处理也可用于数据结构上,比如以任一点为根的前提下的对子树查询

详见https://blog.csdn.net/fsss_7/article/details/51076282

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define rrep(i,j,k) for(int i=j;i>=k;i--)
#define erep(i,u) for(int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
using namespace std;
const int MAXN = 2e5+11;
const int MOD = 1e9+7;
typedef long long ll;
unsigned int xjb=2333333;
int Rand(){
return (xjb=xjb*12345+23333)%MOD+1;
}
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],cost[MAXN<<1],head[MAXN],tot;
int deg[MAXN];
void add(int u,int v,int w){
to[tot]=v;
cost[tot]=w;
nxt[tot]=head[u];
head[u]=tot++;
}
void init(){
memset(head,-1,sizeof head);
tot=0;
}
ll f[MAXN],g[MAXN],n;
void DP(int u,int fa){
f[u]=0;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
ll w=cost[i];
if(v==fa) continue;
DP(v,u);
if(deg[v]==1) f[u]+=w;
else f[u]+=min(w,f[v]);
}
}
void dfs(int u,int fa){
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
ll w=cost[i];
if(v==fa) continue;
g[v]=f[v];
if(deg[u]==1) g[v]+=w;
else g[v]+=min(w,g[u]-min(w,f[v]));
dfs(v,u);
}
}
int main(){
int T=0; cin>>T;
while(T--){
init();
memset(deg,0,sizeof deg);
n=read();
rep(i,1,n-1){
int u=read();
int v=read();
int w=read();
add(u,v,w);
add(v,u,w);
deg[u]++;
deg[v]++;
}
DP(1,0);g[1]=f[1];
dfs(1,0);
ll ans=0;
rep(i,1,n) ans=max(ans,g[i]);
println(ans);
}
return 0;
}

POJ - 3585 树上最大流 换根法的更多相关文章

  1. poj3585树最大流——换根法

    题目:http://poj.org/problem?id=3585 二次扫描与换根法,一次dfs求出以某个节点为根的相关值,再dfs遍历一遍树,根据之前的值换根取最大值为答案. 代码如下: #incl ...

  2. POJ 3585 Accumulation Degree【换根DP】

    传送门:http://poj.org/problem?id=3585 题意:给定一张无根图,给定每条边的容量,随便取一点使得从这个点出发作为源点,发出的流量最大,并且输出这个最大的流量. 思路:最近开 ...

  3. poj 3585 Accumulation Degree(二次扫描和换根法)

    Accumulation Degree 大致题意:有一棵流量树,它的每一条边都有一个正流量,树上所有度数为一的节点都是出口,相应的树上每一个节点都有一个权值,它表示从这个节点向其他出口可以输送的最大总 ...

  4. 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)

    写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...

  5. cf219d 基础换根法

    /*树形dp换根法*/ #include<bits/stdc++.h> using namespace std; #define maxn 200005 ]; int root,n,s,t ...

  6. poj - 3585(二次扫描与换根法)

    周末牛客挂了个更难的,这个简单一些 #include<iostream> #include<cstring> #include<cstdio> #include&l ...

  7. 【51Nod1405】树上距离和 二次扫描与换根法

    题目大意:给定一棵 N 个点的边权均为 1 的树,依次输出每个点到其他各个点的距离和. 题解:首先任意选定一个节点为根节点,比如 1,第一遍 dfs 遍历树求出子树大小.树上前缀和.第二遍 dfs 遍 ...

  8. POJ3585 Accumulation Degree(二次扫描与换根法)

    题目:http://poj.org/problem?id=3585 很容易想出暴力.那么就先扫一遍. 然后得到了指定一个根后每个点的子树值. 怎么转化利用一下呢?要是能找出当前点的父亲的 “ 不含当前 ...

  9. $Poj3585\ Accumulation Degree$ 树形$DP/$二次扫描与换根法

    Poj Description 有一个树形的水系,由n-1条河道与n个交叉点组成.每条河道有一个容量,联结x与y的河道容量记为c(x,y),河道的单位时间水量不能超过它的容量.有一个结点是整个水系的发 ...

随机推荐

  1. EZOJ #224

    传送门 分析 首先我们发现要让答案最小,或运算一定是没有用的 我们还可以发现a^b = a&(~b) 所以异或运算也没有用 于是我们只考虑否和与 我们还会得到一个性质就是没增加一个数一定会让答 ...

  2. NPOI读写Excel sheet操作

    QueryInfo dataInfo = new QueryInfo(); dataInfo.CustomSQL = $@" select t1.name name,t1.url url f ...

  3. AngularJS基本使用

    简介 AngularJS是Google开源的前端JS结构化框架 Angular关注的是动态展示页面数据, 并与用户进行交互.其主体不再是DOM,而是页面中的动态数据 AngularJS特性(优点) 双 ...

  4. javascript和jquery比较

    <h1>我的第一段 JavaScript</h1> <p>请输入数字.如果输入值不是数字,浏览器会弹出提示框.</p> <input id=&qu ...

  5. Android 修改 TextView 的全局默认颜色。

    如果你的应用中大多数TextView的颜色是红色, 或者其他颜色, 你是为每一个TextView都设置一次颜色, 还是有其他更好的办法, 这里教你怎么修改TextView的默认颜色. 当然我们Text ...

  6. CodeForces 347A Difference Row (水题)

    题意:给定 n 个数,让你找出一个排列满足每个数相邻作差之和最大,并且要求字典序最小. 析:这个表达式很简单,就是把重新组合一下,就成了x1-xn,那么很简单,x1是最大的,xn是最小的,中间排序就好 ...

  7. python中return的用法

    def testReturn(x): if x > 10000: return print "test return!!" #这句话永远不会得到执行 elif x > ...

  8. up6-自定义文件存储路径

    在up6.2中有两种保存模式,一种是md5一种是uuid. md5由PathMd5Builder生成存储路径.md5主要提供给文件使用,可在服务器端保存唯一的文件,有效避免重复文件. uuid由Pat ...

  9. Statement 接口的应用(存在sql语句的注入风险)

    实现简单的登录功能 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; impo ...

  10. python语言的jenkinapi

    # coding:utf-8 from jenkinsapi.jenkins import Jenkins # 实例化Jenkins对象,传入地址+账号+密码 j = Jenkins("ht ...