[jzoj 4528] [GDOI2019模拟2019.3.26] 要换换名字 (最大权闭合子图)
题目链接:
https://jzoj.net/senior/#contest/show/2683/0
题目:

题解:
不妨枚举一个点,让两颗树都以这个点为根,求联通块要么点数为$0$,要么包括根(即联通块必须从根开始)
考虑一个不是根的点$x$,若$x$在联通块以内,要保证联通块的连通性,那么从$x$的父亲要在联通块以内
这种一个点选了就必须要选另一个点的问题是典型的最大权闭合子图模型
做法如下
设$s$为源点,$t$为汇点。
使$s$连向所有的正权点(非负权点),边权为点权
使所有非负权点(负权点)连向$t$,边权为点权的绝对值
若需要选$y$就要选$x$,连一条由$x$到$y$的边,边权是$∞$(其实这个地方我一直有疑惑,有的认为是连从$x$到$y$的边,如果有读者知道真相麻烦告诉我)
最大点权和=正权点和-最小割
证明:
我们知道一个割会把图分成两个部分,一部分是$S$能走到的,另一部分是能走到$T$的。
我们设这两个集合为$A$,$B$。
$A0$,$B0$分别表示$A$,$B$中原来点权是负数的点集, $A1$,$B1$分别表示$A$,$B$中点权原来是正数的点集。
由于中间的边是$∞$的,割的一定是和$S$,$T$相连的边,这个叫简单割。
所以割的大小 $= |A0| +B1$
$A,B$一定是最大权闭合子图
$A$的点权和 $= A1 - |A0|$
$A$的点权和+割的大小$=A1 + B1 = $全图中的正权点和
这是一个定值, 要使$A$的点权和最大, 就要使割最小,就是最小割,
至此得证。
代码:
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std; const int N=+;
const int inf=1e9+;
int n,tot1,tot2,cnt;
int a[N],h1[N],h2[N],head[N],dep[N],nowhead[N];
struct EDGE
{
int to,nxt;
}e1[N<<],e2[N<<];
struct node
{
int to,nxt;
int flow;
}edge[N<<];
inline int read()
{
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void link(int u,int v,int w)
{
edge[++cnt]=(node){v,head[u],w};head[u]=cnt;
edge[++cnt]=(node){u,head[v],};head[v]=cnt;
}
void add1(int u,int v)
{
e1[++tot1]=(EDGE){v,h1[u]};
h1[u]=tot1;
}
void add2(int u,int v)
{
e2[++tot2]=(EDGE){v,h2[u]};
h2[u]=tot2;
}
void init()
{
cnt=;
memset(head,-,sizeof(head));
}
void dfs1(int x,int pre)
{
if (pre) link(x,pre,inf);
for (int i=h1[x];i;i=e1[i].nxt)
{
int y=e1[i].to;
if (y==pre) continue;
dfs1(y,x);
}
}
void dfs2(int x,int pre)
{
if (pre) link(x,pre,inf);
for (int i=h2[x];i;i=e2[i].nxt)
{
int y=e2[i].to;
if (y==pre) continue;
dfs2(y,x);
}
}
int S,T;
queue <int> q;
int bfs()
{
memset(dep,,sizeof(dep));
while (!q.empty()) q.pop();
dep[S]=;
q.push(S);
while (!q.empty())
{
int k=q.front();q.pop();
for (int i=head[k];i!=-;i=edge[i].nxt)
if (edge[i].flow&&!dep[edge[i].to])
{
dep[edge[i].to]=dep[k]+;
q.push(edge[i].to);
}
}
return dep[T];
}
int dfs(int x,int a)
{
if (x==T||!a) return a;
int flow=,f;
for (int &i=nowhead[x];i!=-;i=edge[i].nxt)
if (dep[x]+==dep[edge[i].to]&&(f=dfs(edge[i].to,min(a,edge[i].flow)))>)
{
edge[i].flow-=f;
edge[i^].flow+=f;
flow+=f;
a-=f;
if (a==) break;
}
return flow;
}
int dinic()
{
int ans=;
while (bfs())
{
copy(head,head+n+,nowhead);//这行优化重要无比
ans+=dfs(S,inf);
}
return ans;
}
int main()
{
//freopen("theory.in","r",stdin);
int W=read();
while (W--)
{
tot1=;tot2=;
int sum=;
n=read();
S=n+,T=n+;
for (int i=;i<=n;i++)
{
h1[i]=;h2[i]=;
a[i]=read();
if (a[i]>) sum+=a[i];
}
for (int i=;i<n;i++)
{
int u=read(),v=read();
add1(u,v);add1(v,u);
}
for (int i=;i<n;i++)
{
int u=read(),v=read();
add2(u,v);add2(v,u);
}
int res=;
for (int i=;i<=n;i++)
{
init();
dfs1(i,);dfs2(i,);
for (int j=;j<=n;j++) if (a[j]>=) link(S,j,a[j]);else link(j,T,-a[j]);
res=max(res,sum-dinic());
}
printf("%d\n",res);
}
return ;
}
[jzoj 4528] [GDOI2019模拟2019.3.26] 要换换名字 (最大权闭合子图)的更多相关文章
- [jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)
题目链接: https://jzoj.net/senior/#main/show/6086 题目: 题解: 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘 这样的子树 ...
- [jzoj 6087] [GDOI2019模拟2019.3.26] 获取名额 解题报告 (泰勒展开+RMQ+精度)
题目链接: https://jzoj.net/senior/#main/show/6087 题目: 题解: 只需要统计$\prod_{i=l}^r (1-\frac{a_i}{x})$ =$exp(\ ...
- [jzoj 6092] [GDOI2019模拟2019.3.30] 附耳而至 解题报告 (平面图转对偶图+最小割)
题目链接: https://jzoj.net/senior/#main/show/6092 题目: 知识点--平面图转对偶图 在求最小割的时候,我们可以把平面图转为对偶图,用最短路来求最小割,这样会比 ...
- [jzoj 6101] [GDOI2019模拟2019.4.2] Path 解题报告 (期望)
题目链接: https://jzoj.net/senior/#main/show/6101 题目: 题解: 设$f_i$表示从节点$i$到节点$n$的期望时间,$f_n=0$ 最优策略就是如果从$i, ...
- [jzoj 6093] [GDOI2019模拟2019.3.30] 星辰大海 解题报告 (半平面交)
题目链接: https://jzoj.net/senior/#contest/show/2686/2 题目: 题解: 说实话这题调试差不多花了我十小时,不过总算借着这道题大概了解了计算几何的基础知识 ...
- [jzoj 6080] [GDOI2019模拟2019.3.23] IOer 解题报告 (数学构造)
题目链接: https://jzoj.net/senior/#main/show/6080 题目: 题意: 给定$n,m,u,v$ 设$t_i=ui+v$ 求$\sum_{k_1+k_2+...+k_ ...
- [jzoj 6084] [GDOI2019模拟2019.3.25] 礼物 [luogu 4916] 魔力环 解题报告(莫比乌斯反演+生成函数)
题目链接: https://jzoj.net/senior/#main/show/6084 https://www.luogu.org/problemnew/show/P4916 题目: 题解: 注: ...
- jzoj6101. 【GDOI2019模拟2019.4.2】Path
题目链接:https://jzoj.net/senior/#main/show/6101 记\(f_i\)为从\(i\)号点走到\(n\)号点所花天数的期望 那么根据\(m\)条边等可能的出现一条和一 ...
- jzoj6099. 【GDOI2019模拟2019.4.1】Dist
题目链接:https://jzoj.net/senior/#main/show/6099 考虑直接统计某个点到其它所有点的距离和 我们先把整个团当成一个点建图,处理出任意两个团之间的距离\(dis(i ...
随机推荐
- db file sequential read等待事件 --转载
db file sequential read db file sequential read等待事件有3个参数:file#,first block#,和block数量.在10g中,这等待事件受到用户 ...
- 什么是EL表达式
转自:https://blog.csdn.net/hj7jay/article/details/51302466 1. EL表达式主要作用 EL表达式说白了,就是让JSP写起来更加方便,它属于JSP技 ...
- PHP 上传文件到其他服务器
PHP 上传文件到其他服务器 标签(空格分隔): 安装Guzzle类库 **guzzle** 是发送网络请求的类库 composer安装:**composer require guzzlehttp/g ...
- [转]C#多线程和线程池
鸣谢原文:http://www.cnblogs.com/wwj1992/p/5976096.html 1.概念 1.0 线程的和进程的关系以及优缺点 windows系统是一个多线程的操作系统.一个程 ...
- struts2学习之基础笔记1
第6章 Strusts 2框架 1 引出 Web App àà MVC àà View 视图(jsp,html,JS) | C(Servlet)Filter,Listneer | M(数据bea ...
- React组件化开发
环境搭建: 1.安装node.js 2.安装cnpm # npm install -g cnpm --registry=https://registry.npm.taobao.org 3.全局安装c ...
- LeetCode(11)Container With Most Water
题目如下: 题目的意思是求容器能装的最大的水量,当时我按梯形的面积来算,一直不对,后来才发现要按矩形的面积来算 Python代码如下: def maxArea(self, height): " ...
- Unity 需不需要再建Assets文件夹
不需要,默认所有文件都是在Assets文件夹下创建的,看不到是因为设置了单栏模式,开启双栏模式就能看到了.
- Java 面向对象详解
0 引言 接触项目开发也有很长一段时间了,最近开始萌发出想回过头来写写以前学过的基础知识的想法. 1 面向对象 面向对象(Object Oriented)是一种新兴的程序设计方法,或者是一种新的程序设 ...
- WoSign全球可信网站安全认证签章安装指南
您购买了WoSign SSL证书后,将免费获得一个能直观地显示贵网站的认证信息的可信网站安全认证标识,能大大增强用户的在线信任,促成更多在线交易.所以,建议您在安装成功SSL证书后马上在网站的首页和其 ...