题目链接:

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] 要换换名字 (最大权闭合子图)的更多相关文章

  1. [jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)

    题目链接: https://jzoj.net/senior/#main/show/6086 题目: 题解: 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘 这样的子树 ...

  2. [jzoj 6087] [GDOI2019模拟2019.3.26] 获取名额 解题报告 (泰勒展开+RMQ+精度)

    题目链接: https://jzoj.net/senior/#main/show/6087 题目: 题解: 只需要统计$\prod_{i=l}^r (1-\frac{a_i}{x})$ =$exp(\ ...

  3. [jzoj 6092] [GDOI2019模拟2019.3.30] 附耳而至 解题报告 (平面图转对偶图+最小割)

    题目链接: https://jzoj.net/senior/#main/show/6092 题目: 知识点--平面图转对偶图 在求最小割的时候,我们可以把平面图转为对偶图,用最短路来求最小割,这样会比 ...

  4. [jzoj 6101] [GDOI2019模拟2019.4.2] Path 解题报告 (期望)

    题目链接: https://jzoj.net/senior/#main/show/6101 题目: 题解: 设$f_i$表示从节点$i$到节点$n$的期望时间,$f_n=0$ 最优策略就是如果从$i, ...

  5. [jzoj 6093] [GDOI2019模拟2019.3.30] 星辰大海 解题报告 (半平面交)

    题目链接: https://jzoj.net/senior/#contest/show/2686/2 题目: 题解: 说实话这题调试差不多花了我十小时,不过总算借着这道题大概了解了计算几何的基础知识 ...

  6. [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_ ...

  7. [jzoj 6084] [GDOI2019模拟2019.3.25] 礼物 [luogu 4916] 魔力环 解题报告(莫比乌斯反演+生成函数)

    题目链接: https://jzoj.net/senior/#main/show/6084 https://www.luogu.org/problemnew/show/P4916 题目: 题解: 注: ...

  8. jzoj6101. 【GDOI2019模拟2019.4.2】Path

    题目链接:https://jzoj.net/senior/#main/show/6101 记\(f_i\)为从\(i\)号点走到\(n\)号点所花天数的期望 那么根据\(m\)条边等可能的出现一条和一 ...

  9. jzoj6099. 【GDOI2019模拟2019.4.1】Dist

    题目链接:https://jzoj.net/senior/#main/show/6099 考虑直接统计某个点到其它所有点的距离和 我们先把整个团当成一个点建图,处理出任意两个团之间的距离\(dis(i ...

随机推荐

  1. 使用Chrome插件Postman进行简单的Get/Post测试

    转自:https://blog.csdn.net/dearmorning/article/details/56854236 Postman插件: 一种网页调试与发送网页http请求的chrome插件, ...

  2. System.setProperty 与 System.getProperty

    转自:https://www.cnblogs.com/woftlcj/p/8404451.html System可以有对标准输入,标准输出,错误输出流:对外部定义的属性和环境变量的访问:加载文件和库的 ...

  3. Sort和UnSort的小技巧

    Sort和UnSort的小技巧: 记录sortidx,对sortidx再从小到大排序就可以得到用于还原的unsortidx. 对于序列A: sort_idx = np.argsort(A) un_so ...

  4. WPF MVVM 从Prism中学习设计模式之Event Aggregator 模式

    Prism简介 Prism是由微软Patterns & Practices团队开发的项目,目的在于帮助开发人员构建松散耦合的.更灵活.更易于维护并且更易于测试的WPF应用或是Silverlig ...

  5. Exception异常常见属性

    废话少说,直接上代码: try { int n = Convert.ToInt32("@"); } catch(Exception ex) { Console.WriteLine( ...

  6. ASP.NET MVC+Bootstrap分页Helper

    <div class="pagination"> <ul> //************分页HTML********* </ul> </d ...

  7. 《鸟哥的Linux私房菜》笔记——03. 磁盘分区

    Everything is a file. 常见硬件对应于 Linux 下的文件(/dev目录下) 装置 装置在Linux内的档名 SCSI/SATA/U盘硬盘机 /dev/sd[a-p] U盘 /d ...

  8. css——定位

    position absolute:绝对定位 1.以页面的左上角为原点 2.不保留原来的位置 3.z-index可以调整图层顺序 如果想实现以父级元素左上角为原点.则:父级相对,子级绝对 在子级绝对的 ...

  9. node——简单的服务器启动+乱码问题解决,响应报文头

    这个是一个比较简单的代码 // 1.加载hrrp模块 var http=require('http'); // 2.创建一个http服务对象 var server=http.createServer( ...

  10. How to debug systemd step by step

    docker run -ti --name systemd --net host --privileged reg.docker.xxxxxxxx:latest /usr/lib/systemd/sy ...