https://codeforces.com/contest/1061/problem/E

题意

有n个点(<=500),标记第i个点的代价a[i],然后分别在这n个点建两棵树,对于每颗树的每个点来说,都有一个p[i],代表他的子树中被标记的点的个数需要等于p[i],请你选择需要标记的点,使得可以满足上述两棵树的要求,并且使得代价最大,输出最大的代价或者-1(不存在)

思路

  • 这道题难在建图
  • 首先考虑子树问题,是否选择每个节点对他的子孙节点没有影响,但是对他自身及其祖先节点有影响,注意p[i]=0代表i的子树没有限制

    假设v为u的子孙节点且p[u]>0(有限制),sum=p[v1]+p[v2]+..+p[vn],

    sum>p[u],则对于本棵树来说不存在满足条件的选点情况

    sum<=p[u],则剩下p[u]-sum的空间给本棵树和另外一颗树选择

  • 设col[u]为最靠近u的有限制的祖先节点(包括u),那么选择u就等于填充了两棵树的col[u]节点
  • 所以可以这样建图,建超源超汇S,T,将第一颗树的点和源点相连,cap=p[u]-sum,cost=0,将第二颗树的点和汇点相连,cap=p[u]-sum,cost=0,将两棵树之间的点col1[u]和col2[u]相连,cap=1,cost=-a[u],跑一个mcmf
  • 还需要判一下左边容量等于右边容量并且最大流等于容量,才能存在满足条件的选点情况
#include<bits/stdc++.h>
#define N 2005
#define M 4000000
#define inf 0x3f3f3f3f
using namespace std;
int n,rt1,rt2,ent,S,T,i,u,v,q,x,hd[N],p[N],col[N],f[N],d[N],inq[N],pre[N],a[N];
int flow,cost,ans,in,out; struct edge{
int u,v,nt,c,w;
edge(int u=0,int v=0,int nt=0,int c=0,int w=0):u(u),v(v),nt(nt),c(c),w(w){}
}E[M]; void fail(){
cout<<-1;exit(0);
}
void add(int u,int v,int c,int w){
E[++ent]=edge(u,v,hd[u],c,w);hd[u]=ent;
E[++ent]=edge(v,u,hd[v],0,-w);hd[v]=ent;
}
int dfs(int u,int fa,int tar){
if(p[u])tar=u;
col[u]=tar;
int cnt=0,tp=p[u];
for(int i=hd[u];i;i=E[i].nt){
int v=E[i].v;
if(v==fa)continue;
cnt+=dfs(v,u,tar);
}
if(p[u]){if(p[u]<cnt)fail();p[u]-=cnt;cnt=tp;}
return cnt;
} int bf(){
queue<int>Q;
for(i=0;i<=T;i++)d[i]=inf;
memset(inq,0,sizeof(inq));
d[S]=0;inq[S]=1;pre[S]=0;f[S]=inf;Q.push(S); while(!Q.empty()){
int u=Q.front();Q.pop();
inq[u]=0;
for(int i=hd[u];i;i=E[i].nt){
edge &e=E[i];
if(e.c&&d[e.v]>d[u]+e.w){
d[e.v]=d[u]+e.w;
pre[e.v]=i;
f[e.v]=min(f[u],e.c);
if(!inq[e.v]){inq[e.v]=1;Q.push(e.v);}
}
}
}
return d[T]<inf;
} void mcmf(){
if(in!=out)fail();
flow=0;cost=0;
while(bf()){
flow+=f[T];cost-=d[T]*f[T];
for(int i=T;i!=S;i=E[pre[i]].u){
E[pre[i]].c-=f[T];
E[pre[i]^1].c+=f[T];
}
}
if(flow!=in)fail();
cout<<cost<<endl;
} int main(){
cin>>n>>rt1>>rt2;rt2+=n;
ent=1;S=2*n+1;T=2*n+2;
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=0;i<n-1;i++){scanf("%d%d",&u,&v);add(u,v,0,0);}
for(i=0;i<n-1;i++){scanf("%d%d",&u,&v);u+=n;v+=n;add(u,v,0,0);}
cin>>q;
for(i=0;i<q;i++){scanf("%d%d",&u,&x);p[u]=x;}
cin>>q;
for(i=0;i<q;i++){scanf("%d%d",&u,&x);p[u+n]=x;}
dfs(rt1,0,rt1);dfs(rt2,0,rt2); memset(hd,0,sizeof(hd));ent=1;
in=out=0;
for(i=1;i<=n;i++){in+=p[i];if(p[i])add(S,i,p[i],0);}
for(i=1;i<=n;i++){out+=p[i+n];if(p[i+n])add(i+n,T,p[i+n],0);}
for(i=1;i<=n;i++)add(col[i],col[i+n],1,-a[i]);
mcmf();
}

Codeforces Round #523 (Div. 2) E. Politics(最小费+思维建图)的更多相关文章

  1. Codeforces Round #580 (Div. 2)-D. Shortest Cycle(思维建图+dfs找最小环)

    You are given nn integer numbers a1,a2,…,ana1,a2,…,an. Consider graph on nn nodes, in which nodes ii ...

  2. Codeforces Round #406 (Div. 2) D. Legacy (线段树建图dij)

    D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  3. Codeforces Round #523 (Div. 2)

    Codeforces Round #523 (Div. 2) 题目一览表 来源 考察知识点 完成时间 A Coins cf 贪心(签到题) 2018.11.23 B Views Matter cf 思 ...

  4. Codeforces Round #521 (Div. 3) E. Thematic Contests(思维)

    Codeforces Round #521 (Div. 3)  E. Thematic Contests 题目传送门 题意: 现在有n个题目,每种题目有自己的类型要举办一次考试,考试的原则是每天只有一 ...

  5. Codeforces Round #523 (Div. 2) F. Katya and Segments Sets (交互题+思维)

    https://codeforces.com/contest/1061/problem/F 题意 假设存在一颗完全k叉树(n<=1e5),允许你进行最多(n*60)次询问,然后输出这棵树的根,每 ...

  6. Codeforces Round #523 (Div. 2) Solution

    A. Coins Water. #include <bits/stdc++.h> using namespace std; int n, s; int main() { while (sc ...

  7. Codeforces Round #523 (Div. 2) Cdp

    题:https://codeforces.com/contest/1061/problem/C 题意:给你一个序列,我们求他们子序列的个数,这个子序列有个限制就是每一个子序列上的值都必须是能整除他的下 ...

  8. Codeforces Round #523 (Div. 2) D. TV Shows 模拟(多重集 先把所有区间加入多重集合)+贪心+二分

    题意:给出n个电视节目的起始和结束时间  并且租一台电视需要x +y*(b-a)  [a,b]为时段 问完整看完电视节目的最小花费是多少 思路:贪心的思想 情况1 如果新租一台电视的花费<=在空 ...

  9. Codeforces Round #523 (Div. 2) D. TV Shows

    传送门 https://www.cnblogs.com/violet-acmer/p/10005351.html 题意: 有n个节目,每个节目都有个开始时间和结束时间. 定义x,y分别为租电视需要的花 ...

随机推荐

  1. Qt: 记事本源代码

    界面编程之实例学习,系统记事本是个极好的参考,初学Delphi及后之c#,皆以记事本为参考,今以Qt学习,亦是如此. 期间搭建开发环境,复习c++知识,寻找模块对应功能,不一而足:现刻录其模块代码,以 ...

  2. Ansible Playbook 详解

    一.playbook 的简单使用 1.创建文件实例 (1)编辑配置文件 [root@tiejiangSRC1 ~]# cd /etc/ansible/ [root@tiejiangSRC1 ansib ...

  3. android的图片的初步学习理解

    Android支持JPEG和PNG格式.GIF和BMP格式图片的支持. 图片最终要显示在屏幕上,都会对应一个屏幕上的点,即对应一个颜色值.不同格式的图片,只是不同压缩编码和解压算法. 也就是说,我们看 ...

  4. MyBatis入门程序(1)

    一.入门程序: 1.mybatis的配置文件SqlMapConfig.xml 配置mybatis的运行环境,数据源.事务等. <?xml version="1.0" enco ...

  5. 42-2017蓝桥杯b java

    1.购物单    小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞.    这不,XX大促销又来了!老板夫人开出了长长的购物单,都 ...

  6. xshell实时跟踪日志与中文乱码设置

    1.实时跟踪日志命令 tail -f logName.log 动态查看名为logName的日志信息 ctrl+c 退出实时跟踪 2.中文乱码设置 在Xshell.putty.SSH Secure Sh ...

  7. go语言使用go-sciter创建桌面应用(三) 事件处理,函数与方法定义,go与tiscript之间相互调用

    sciter处理脚本tiscript,用于处理UI交互中的一些逻辑,跟js很像,但又有点区别,对前端熟悉的人应该能很快上手. tiscrip脚本文档 https://sciter.com/develo ...

  8. 微信网页JS分享,微信二次分享无缩略图问题

    很多时候我们要在微信中分享h5网页,这个时候就得用微信的分享接口来自定义分享的地址.标题.描述.缩略图了. 分享到微信的时候遇到一个问题,就是第一次分享到微信里,是正确的,但是在微信打开分享的链接,再 ...

  9. asp.net core webapi 日期返回中出现字母T

    全局配置 在Startup文件中修改 // This method gets called by the runtime. Use this method to add services to the ...

  10. python 面向对象编程 之 析构方法

    析构方法:当对象在内存中被释放的时候,自动触发执行 如果产生的对象仅仅只是用户级别的, 那么无需定义__del__,如果对象还会向操作系统发生系统调用, 即一个对象有用户级别与内核级两种资源, 比如打 ...