牛客暑期第六场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 ...
随机推荐
- Python pillow库安装报错
报错信息: D:\pythontest\duanxinhongzha>pip3 install pillowCollecting pillow Could not find a version ...
- BZOJ 3626: [LNOI2014]LCA(树剖+差分+线段树)
传送门 解题思路 比较有意思的一道题.首先要把求\(\sum\limits_{i=l}^r dep[lca(i,z)]\)这个公式变一下.就是考虑每一个点的贡献,做出贡献的点一定在\(z\)到根节点的 ...
- NX二次开发-将对象移动到图层UF_OBJ_set_layer
#include <uf.h> #include <uf_obj.h> #include <uf_modl.h> #include <uf_layer.h&g ...
- golang的select典型用法
golang 的 select 的功能和 select, poll, epoll 相似, 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作. 示例: ch1 := make (chan in ...
- Python 查看QQ状态
import requests """ 该程序依赖于QQ的端口程序 返回数据:String,Y = 在线:N = 离线:E = QQ号码错误:A = 商业用户验证失败:V ...
- 数据结构C++版-栈
一.概念 二.应用实例 1.进制转换 #include <stdlib.h> #include <iostream> #include <string> #incl ...
- 微信-小程序-开发文档-服务端-模板消息:templateMessage.getTemplateLibraryList
ylbtech-微信-小程序-开发文档-服务端-模板消息:templateMessage.getTemplateLibraryList 1.返回顶部 1. templateMessage.getTem ...
- SPSS缺失值得分析处理
SPSS缺失值得分析处理 在资料收集的过程中,由于各种原因可能导致数据收集不全,就会产生缺失值,且这种情况往往无法避免.如果缺失值处理不当,就会导致分析结果精度降低,出现偏倚甚至是错误的理论,因此缺失 ...
- 在Debian中安装VNC Server
大部分情况下我们用ssh就可以登录linux服务器了.但有时候我们的程序需要在图形界面下运行,这时我们就要用到vnc server这个软件了. 在Debian下安装vnc server很简单的,只要几 ...
- python array基本操作一
一.排序 a = [2,3,4,1] b = np.argsort(a) # out:[3 0 1 2] # 输出:是一个数组,是按元素递增顺序的索引 二.查找 1.最大值及其索引 b = max(a ...