CF1061E Politics E. Politics

考虑利用树的性质,因为是子树问题,所以放到dfs序上。

只考虑一个树,问题是每个区间选恰好\(k\)个。因为区间其实是子树,所以区间要么包含,要么不交。

所以可以把区间拆开,拆开很多个互相独立的区间。

问题就变成了有若干个,从每个集合中选择\(k_i\)个数字,最大化权。

考虑两棵树的情况,每个点选择或者不选择,又恰好只有两颗树,考虑费用流

\(s\)连每个条件的虚点,流量为\(k_i\),边权为\(0\),这个虚点连可以选择的点集的每个点,流量\(1\),边权\(0\)

然后另一个集合同理连\(t\)

点自己拆一下点就可以了。


Code:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <vector>
#include <algorithm>
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
int f=0;x=0;char c=gc();
while(!isdigit(c)) f|=c=='-',c=gc();
while(isdigit(c)) x=x*10+c-'0',c=gc();
if(f) x=-x;
}
const int N=2020,M=5010;
int n,m,q0,q1,s,t,x,y;
int head[N],to[M],Next[M],edge[M],cost[M],cnt=1;
void add(int u,int v,int w,int c)
{
to[++cnt]=v,edge[cnt]=w,cost[cnt]=c,Next[cnt]=head[u],head[u]=cnt;
to[++cnt]=u,edge[cnt]=0,cost[cnt]=-c,Next[cnt]=head[v],head[v]=cnt;
}
int q[N*N],pre[N],dis[N],l,r;
bool spfa()
{
memset(dis,-0x3f,sizeof dis);
dis[q[l=r=1]=s]=0;
while(l<=r)
{
int now=q[l++];
for(int v,i=head[now];i;i=Next[i])
if(edge[i]&&dis[v=to[i]]<dis[now]+cost[i])
{
dis[v]=dis[now]+cost[i];
pre[q[++r]=v]=i;
}
}
return dis[t]!=dis[0];
}
int sta[N],tot,id[N],siz[N],ned[N],eu[N],ev[N],toki;
std::vector <int> E[N];
void dfs1(int now,int fa)
{
sta[++tot]=now;
for(int v,i=0;i<E[now].size();i++)
if((v=E[now][i])!=fa)
dfs1(v,now),siz[now]+=siz[v];
if(id[now])
{
if(ned[now]-siz[now]<0) toki=1;
add(s,id[now],ned[now]-siz[now],0);
siz[now]=ned[now];
int k;
do
{
k=sta[tot--];
add(id[now],k,1,0);
}while(k!=now);
}
}
void dfs2(int now,int fa)
{
sta[++tot]=now;
for(int v,i=0;i<E[now].size();i++)
if((v=E[now][i])!=fa)
dfs2(v,now),siz[now]+=siz[v];
if(id[now])
{
if(ned[now]-siz[now]<0) toki=1;
add(id[now],t,ned[now]-siz[now],0);
siz[now]=ned[now];
int k;
do
{
k=sta[tot--];
add(k+n,id[now],1,0);
}while(k!=now);
}
}
int main()
{
read(n),read(x),read(y);
for(int w,i=1;i<=n;i++) read(w),add(i,i+n,1,w);
m=2*n,s=++m,t=++m;
for(int u,v,i=1;i<n;i++) read(u),read(v),E[u].push_back(v),E[v].push_back(u);
for(int i=1;i<n;i++) read(eu[i]),read(ev[i]);
read(q0);
int mx;
for(int a,i=1;i<=q0;i++)
{
read(a),read(ned[a]);
id[a]=++m;
if(a==x) mx=ned[a];
}
dfs1(x,0);
memset(ned,0,sizeof ned);
memset(id,0,sizeof id);
memset(siz,0,sizeof siz);
for(int i=1;i<=n;i++) E[i].clear();
for(int i=1;i<n;i++) E[eu[i]].push_back(ev[i]),E[ev[i]].push_back(eu[i]);
read(q1);
for(int a,i=1;i<=q1;i++)
{
read(a),read(ned[a]);
id[a]=++m;
if(a==y&&mx!=ned[a]) toki=1;
}
dfs2(y,0);
if(toki)
{
puts("-1");
return 0;
}
int flow=0,ans=0;
while(spfa())
{
++flow;
ans+=dis[t];
int now=t;
while(now!=s)
{
--edge[pre[now]];
++edge[pre[now]^1];
now=to[pre[now]^1];
}
}
if(flow==mx) printf("%d\n",ans);
else puts("-1");
return 0;
}

2019.6.1

CF1061E Politics E. Politics 解题报告的更多相关文章

  1. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  2. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  3. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

  4. 习题:codevs 2822 爱在心中 解题报告

    这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...

  5. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

  6. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  7. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

  8. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  9. LeetCode 解题报告索引

    最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中......                        ...

随机推荐

  1. S1 Python 基础

    定义规范 声明变量 name = "Alex Li" 变量定义规则 变量名只能是 字母.数字或下划线的任意组合 变量名的第一个字符不能是数字 以下关键字不能声明为变量名['and' ...

  2. 树结构遍历节点名字提取,这里提取的是el-tree数据结构,封装成函数

    /** * 树形数据提取节点 * @param {*} data */ export function treeDataGetnode (data) { var res = [] var child= ...

  3. Instagram几个queryhash

    page_query_hash 42323d64886122307be10013ad2dcc44comment_query_hash 33ba35852cb50da46f5b5e889df7d159f ...

  4. python打印9宫格,25宫格等奇数格,且横竖斜相加和相等

    代码如下: #!/usr/bin/env python3#-*- coding:utf-8 -*-num = int(input('请输入一个奇数:'))# 定义一个长为num的列表high = [[ ...

  5. linux设备驱动第二篇:构造和运行模块

      上一篇介绍了Linux驱动的概念,以及linux下设备驱动的基本分类情况及其各个分类的依据和差异,这一篇我们来描述如何写一个类似hello world的简单测试驱动程序.而这个驱动的唯一功能就是输 ...

  6. LINK : fatal error LNK1561: 必须定义入口点

    转自VC错误:http://www.vcerror.com/?p=1313 问题描述: 错误:LINK : fatal error LNK1561: 必须定义入口点 解决方法: 详细的解决方法可参考V ...

  7. 20150709---Web中GridView控件根据绑定的数据显示不同的图片

    示例图: 根据数据判断,显示各种不同的图片 该列的前端代码: <asp:TemplateField HeaderText="审图"> <ItemTemplate& ...

  8. js不同类型作比较

    引用自 http://www.zhufengpeixun.cn/jishuziliao/javaScriptzhuanti/2014-06-14/300.html 不同类型间的比较,规律如下 类型 类 ...

  9. Php安装时出现的问题处理

    问题从这里开始,我们一步一步说明: cd /usr/local/src/ tar zxvf php-5.5.6.tar.gz cd php-5.5.6 ./configure \ //执行当前目录下软 ...

  10. 通过TCP/IP连接Mysql数据库

    问题:mysql只能用localhost或127.0.0.1连接 解决:mysql安装完后,默认是root用户,root用户只能在服务器登录,需要分配新用户. 1.以root用户登陆mysql数据库. ...