CF1061E Politics E. Politics 解题报告
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 解题报告的更多相关文章
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- 习题: codevs 2492 上帝造题的七分钟2 解题报告
这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...
- 习题:codevs 1519 过路费 解题报告
今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...
- NOIP2016提高组解题报告
NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合
- LeetCode 解题报告索引
最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中...... ...
随机推荐
- php str_split()函数 语法
php str_split()函数 语法 str_split()函数怎么用 php str_split()函数用于把字符串分割到数组中,语法是str_split(string,length),将字符串 ...
- delphi按字节长度分割字符串函数(转)
此字符串分割函数用delphi编写,可以适应字符串中存在双字节字符和单字节字符. function TricheditEfm.SplitString(source:string;Sleng:Integ ...
- hdu 5181 numbers——思路+区间DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5181 题解:https://www.cnblogs.com/Miracevin/p/10960717.ht ...
- speike
speike 题目描述 众所周知,Speike 狗是一条特别喜欢追着Tom 打的狗. 现在,Tom 又把Speike 惹生气了,现在Speike 需要跨越千山万水找Tom 报仇. Speike 所在的 ...
- [CSP-S模拟测试]:涂色游戏(DP+组合数+矩阵快速幂)
题目描述 小$A$和小$B$在做游戏.他们找到了一个$n$行$m$列呈网格状的画板.小$A$拿出了$p$支不同颜色的画笔,开始在上面涂色.看到小$A$涂好的画板,小$B$觉得颜色太单调了,于是把画板擦 ...
- IIS的站点配置存储在applicationHost.config
C:\Windows\System32\inetsrv\Config\applicationHost.config
- iOS图片压缩问题
对于压缩的处理我给出的建议是 先判断 图片的大小,如果是本地图片最好用nsfilemanager 来判断 .如果不能用这个判断的话 就只能先将图片转成data,然后再判断了. 图片转成data 当然就 ...
- 建站手册-浏览器信息:Mozilla 项目
ylbtech-建站手册-浏览器信息:Mozilla 项目 1.返回顶部 1. http://www.w3school.com.cn/browsers/browsers_mozilla.asp 2. ...
- Java学习之Thread方法
一.sleep()方法:在同步中,释放CPU执行权,不释放同步锁,意味着程序停止 二.停止线程方法:原理:run执行完成 1.设置标记 class StopThread implements Runn ...
- Mac版-Jdk安装与环境配置
下载安装 oracle官网下载,地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html 下载好后,点击安装包,一直 ...