牛客暑期第六场G /// 树形DP 最大流最小割定理
题目大意:
输入t,t个测试用例
每个测试用例输入n
接下来n行 输入u,v,w,树的无向边u点到v点权重为w
求任意两点间的最大流的总和
1.最大流最小割定理 即最大流等于最小割
2.无向树上的任意两点都可互达 也就是说 源点S可经其他任何点流到汇点T
设dist(x , y) 为在树上 x 到 y 的距离
由2能知道,S的总流量就是 n∑i=1 dis( s , i )
然后就是题解上的 S到其他各个点的距离 和 T到其他各个点的距离 中较小的即为最小割

举个栗子
4
1 2 3
1 3 4
3 4 5

通过树形DP
ll dis[MAXN], son[MAXN], dp[MAXN]; /// dis[ i ]为从 i 点向下的分支的长度总和
/// son[ i ]为从 i 点向下的总点数(包括它本身)
/// dp[ i ]为从 i 点出发去其他所有点的长度总和 void dfs1(ll u,ll f) /// 求dis[],son[]
{
son[u]=;
for(int i=;i<vec[u].size();i++) {
ll v=vec[u][i].F, w=vec[u][i].S;
if(v==f) continue;
dfs1(v,u);
son[u]+=son[v];
dis[u]+=dis[v]+son[v]*w;
}
} void dfs2(int u,int f) /// 通过dis[]进行树形DP
{
for(int i=;i<vec[u].size();i++) {
ll v=vec[u][i].F, w=vec[u][i].S;
if(v==f) continue;
dp[v]=dp[u]+(n-*son[v])*w;
dfs2(v,u);
}
}
...... dfs1(,); dp[]=dis[]; dfs2(,); ......
/*结果为
dis[] 16 0 5 0
son[] 4 1 2 1 dp[] 16 22 16 26
*/
可以转化为一个(姑且称之为)流量图

括号内的是到该点的总流量
那么 S到T的最大流 就是 两者总流量中 小的一个
sort(dp+,dp++n);
__int128 ans=;
for(int i=;i<n;i++)
ans += dp[i]*(n-i);
当某个点x的总流量是所有点中的最小值时
那么x与其他所有点的最大流就是x的总流量
所以这里可以直接贪心 排序一下
第 i 个点与后面比它(的总流量)小的所有点(n - i 个)直接取第 i 个
也可以不用 __int128 ,开个数组模拟一下
int ans[];
memset(ans,,sizeof(ans));
for(ll i=;i<n;i++) {
ans[] += dp[i]*(n-i);
int j=;
while(ans[j]>=) {
ans[j+] += ans[j]/;
ans[j++] %= ;
}
len=max(len,j);
}
printf("Case #%d: %lld",o,ans[len]);
for(int i=len-;i>=;i--) {
if(ans[i]>=) printf("%lld",ans[i]);
else if(ans[i]>=) printf("0%lld",ans[i]);
else printf("00%lld",ans[i]);
} printf("\n");
完整代码
#include <bits/stdc++.h>
#define P pair<ll,ll>
#define mp(i,j) make_pair(i,j)
#define F first
#define S second
#define MAXN 100005
#define ll long long
using namespace std; vector <P> vec[MAXN];
ll dis[MAXN], son[MAXN], dp[MAXN];
ll n, m, ans[MAXN]; void dfs1(ll u,ll f)
{
son[u]=;
for(int i=;i<vec[u].size();i++) {
ll v=vec[u][i].F, w=vec[u][i].S;
if(v==f) continue; dfs1(v,u); son[u]+=son[v];
dis[u]+=dis[v]+son[v]*w;
}
} void dfs2(int u,int f)
{
for(int i=;i<vec[u].size();i++) {
ll v=vec[u][i].F, w=vec[u][i].S;
if(v==f) continue; dp[v]=dp[u]+(n-*son[v])*w; dfs2(v,u);
}
} int main()
{
int t; scanf("%d",&t);
for(int o=;o<=t;o++) {
for(int i=;i<=n;i++) vec[i].clear();
memset(dis,,sizeof(dis));
memset(son,,sizeof(son));
memset(dp,,sizeof(dp)); scanf("%lld",&n);
for(int i=;i<n;i++) {
ll u,v,w; scanf("%lld%lld%lld",&u,&v,&w);
vec[u].push_back(mp(v,w));
vec[v].push_back(mp(u,w));
} dfs1(,); dp[]=dis[]; dfs2(,);
sort(dp+,dp++n); int len=;
memset(ans,,sizeof(ans));
for(ll i=;i<n;i++) {
ans[] += dp[i]*(n-i);
int j=;
while(ans[j]>=) {
ans[j+] += ans[j]/;
ans[j++] %= ;
}
len=max(len,j);
} printf("Case #%d: %lld",o,ans[len]);
for(int i=len-;i>=;i--) {
if(ans[i]>=) printf("%lld",ans[i]);
else if(ans[i]>=) printf("0%lld",ans[i]);
else printf("00%lld",ans[i]);
} printf("\n");
} return ;
}
数组模拟
#include <bits/stdc++.h>
#define P pair<int,int>
#define mp(i,j) make_pair(i,j)
#define F first
#define S second
#define MAXN 100005
using namespace std;
vector <P> vec[MAXN];
int son[MAXN];
int n, m;
__int128 dis[MAXN], dp[MAXN]; void dfs1(int u,int f)
{
son[u]=;
for(int i=;i<vec[u].size();i++) {
int v=vec[u][i].F, w=vec[u][i].S;
if(v==f) continue; dfs1(v,u); son[u]+=son[v];
dis[u]+=dis[v]+son[v]*w;
}
} void dfs2(int u,int f)
{
for(int i=;i<vec[u].size();i++) {
int v=vec[u][i].F, w=vec[u][i].S; if(v==f) continue; dp[v]=dp[u]+(n-*son[v])*w; dfs2(v,u);
}
} void print(__int128 ans)
{
if(ans>) print(ans/);
printf("%c",''+ans%);
} int main()
{
int t; scanf("%d",&t);
for(int o=;o<=t;o++) { for(int i=;i<=n;i++) vec[i].clear();
memset(dis,,sizeof(dis));
memset(son,,sizeof(son));
memset(dp,,sizeof(dp)); scanf("%d",&n);
for(int i=;i<n;i++) {
int u,v,w; scanf("%d%d%d",&u,&v,&w);
vec[u].push_back(mp(v,w));
vec[v].push_back(mp(u,w));
} dfs1(,); dp[]=dis[]; dfs2(,); sort(dp+,dp++n);
__int128 ans=;
for(int i=;i<n;i++)
ans += dp[i]*(n-i); printf("Case #%d: ",o);
print(ans);printf("\n");
} return ;
}
__int128
牛客暑期第六场G /// 树形DP 最大流最小割定理的更多相关文章
- run (牛客多校第二场)计数DP
链接:https://www.nowcoder.com/acm/contest/140/A来源:牛客网 题目描述 White Cloud is exercising in the playground ...
- 牛客练习赛32B Xor Path (树形dp)
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 给定一棵n个点的树,每个点有权值.定义表示 ...
- [2019牛客多校第二场][G. Polygons]
题目链接:https://ac.nowcoder.com/acm/contest/882/G 题目大意:有\(n\)条直线将平面分成若干个区域,要求处理\(m\)次询问:求第\(q\)大的区域面积.保 ...
- 牛客多校第二场 G transform
链接:https://www.nowcoder.com/acm/contest/140/G White Cloud placed n containers in sequence on a axes. ...
- 二分图最佳匹配KM算法 /// 牛客暑期第五场E
题目大意: 给定n,有n间宿舍 每间4人 接下来n行 是第一年学校规定的宿舍安排 接下来n行 是第二年学生的宿舍安排意愿 求满足学生意愿的最少交换次数 input 2 1 2 3 4 5 6 7 8 ...
- 2019牛客竞赛第六场D Move 宏观单调,部分不单调
Move 题意 有k个体积相同的箱子,有个憨憨有固定的装箱策略,每次都只装可以装的重量中最大的东西,求箱子的最小提及 分析 看起来可以二分,但由于他的装箱策略有点蠢,所以只在宏观上满足单调性,在特别小 ...
- 牛客小白月赛3---G 旅游(树形dp)
题目链接:https://www.nowcoder.com/acm/contest/87/G 分析: 1.对于点cur,dp[cur][0]表示在该点住宿:dp[cur][1]表示其某个子结点住宿,自 ...
- 2019牛客多校第一场 E-ABBA(dp)
ABBA 题目传送门 解题思路 用dp[i][j]来表示前i+j个字符中,有i个A和j个B的合法情况个数.我们可以让前n个A作为AB的A,因为如果我们用后面的A作为AB的A,我们一定也可以让前面的A对 ...
- 【牛客】路径计数机 (树形dp 前缀和)
题目描述 有一棵n个点的树和两个整数p, q,求满足以下条件的四元组(a, b, c, d)的个数: 1.$1\leq a,b,c,d \leq n$ 2.点a到点b的经过的边数为p. 3.点c ...
随机推荐
- vue-cli 新手 搭建项目 一
新手入坑vue 搭建项目 一.安装 vue-cli 1.打开cmd 输入命令(已自行安装好npm node等) npm install --global vue-cli (全局安装) 二.创建项 ...
- sizeof,真正终结版GCC与VC
在VC6.0中sizeof结果是16.我电脑上装了个linux虚拟机,在虚拟机上GCC中结果是12, 恩不同编译器默认对齐数值不一样. VC 默认为 8 gcc 默认为 4 有个编译参数控制对齐. # ...
- 2019 USP Try-outs 练习赛
// 好久没更博客了,最近打了很多场练习赛&校内PK赛,大概自闭忙于补题吧 // 9.26 周四练习赛 A. Kolkhozy 题意 有 n 个数 \(f[i]\) ,有 q 次询问(l, r ...
- Python匹马行天下之面向对象
概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 面向过程编程最易被初学 ...
- 自学之linux的基本命令
cd cd 用于进入指定文件夹 cd ..用于回到上个文件夹 ls ls用于列出文件夹里的所有元素 ls/home/ 列出home文件夹的元素 ls -l 可以看到文件名,拥有者是谁,什么时候修改的 ...
- 通过快递100获取快递单号,结合c-lodop热敏纸打印 – 通过菜鸟ISV/自研ERP使用菜鸟电子面单
https://www.1024cc.cn/index.php/2019/04/29/%E6%89%93%E5%8D%B0%E7%94%B5%E5%AD%90%E9%9D%A2%E5%8D%95/ 打 ...
- asp.net Core 使用redis(StackExchange.Redis)
原文:asp.net Core 使用redis(StackExchange.Redis) 一.添加配置(appsettings.json) "Redis": { "Def ...
- python接口自动化(get请求)
python接口自动化(get请求) get请求的目的:查询资源 一.导包 二.请求的URL 三.请求的参数 四.获取请求的URL 五.获取响应的状态码 六.获取响应的本文信息 #导包 import ...
- linux 下安装maven私服
1.下载最新nexus安装包 下载地址:https://www.sonatype.com/download-oss-sonatype 2.下载JDK7,nexus2版本支持JDK7:nexus1版本支 ...
- K8S之WebApi部署
转载声明 本文转自:ASP.NET Core on K8S学习初探(3)部署API到K8S 1.下载镜像 docker pull edisonsaonian/k8s-demo 因为是测试流程,直接把文 ...