[jzoj]1729.blockenemy
Link
https://jzoj.net/senior/#main/show/1729
Description
你在玩电子游戏的时候遇到了麻烦。。。。。。
你玩的游戏是在一个虚拟的城市里进行,这个城市里有n个点,都从0~n-1编了号,每两个点之间有且仅有一条路径。现在,你的敌人到这个城市来踩点了!!!为了阻止他们更好的踩点, 你决定切断他们所有踩点人员的联系,使他们孤军作战,然后在各个击破。但是这就要切断某些街道,而你每切断一条路,市民就会产生相对的不满值,不满值越大,城市的和谐度就越小。
所以你现在需要知道为了使踩点人员所在的点两两之间不联通所切断的边产生的最小不满值是多少?
Solution
40分
判断每条边选不选,就可以了
100分
这道题是一道很好的树形DP练手题目,同时也可以用并查集+贪心来做,现在讲一下两种做法
(1)树形DP
设f[x]表示以x为根,它子树的敌人都不可以互相联络,且无法到达点x的最小价值
设g[x]表示以x为根,它子树的敌人都不可以互相联络,但是其中一个敌人可以到达x这个点的最小价值
这个状态设得异常巧妙,在我看过这道题的所有题解,这是最好理解的
其实,解题的关键,就是状态和转移上面了!
我们考虑两种情况,如果当前x上有敌人,或者没有敌人,应该怎么做。
①有敌人
如果有敌人,那么f[x]就赋值为无穷大,因为他根本不可以“无法到达点x”
这时,我们考虑g[x]给之后的转移用,到底g[x]应该是多少
显然是g[x]=∑min(f[y],g[y]+dis[x,y]),(y是x的儿子)为什么呢?
因为x这个点有敌人了,那么g[x]本身就符合条件了
因为f[y]的时候,没有点可以互相联络,如果多添一个点x,那么他就是g[x]的条件了,所以它是取最小值的两个数之一
因为g[y]已经符合条件了,如果多添一个点x,那么他就不符合g[x]的条件了,因为他有2个点可以到达x,所以我们需要x~y之间连一条边,保证只有1个点可以到达x
②无敌人
f[x]=∑min(f[y],g[y]+dis[x,y])(y是x的儿子)为什么呢?
跟上面g数组的转移差不多
f[y]是符合条件的,所以多添一个点还是fx的条件,所以是取最小值的两个数之一、
g[y]是不符合条件的,他有1个点可以到达x,所以x~y之间连一条边,保证没有点可以到达x
可是,这时,g[x]怎么做的?怎么转移是本题解题的关键所在
g[x]一定是在f[x]的基础上转移的!使得它的某个儿子不可以到达
其实,就是把f[x]中,一个花费最大的一次删除敌人到x的边的价值,删掉
重点
上面说了f[x]=min(f[y],g[y]+dis[x,y])(其中一个),我们把可以到达x这个点,变成不可以到达这个点,然后就有两种情况
一种就是g[y]+dis,如下图
试想一下,原本y点为根的子树是可以到达y的,但是删去了x~y之间的边就不可以到达了,也就是说,是从未知点~x~y的,是这样的顺序
还有一种情况就是f[y],同上图
就是原本的
我们由min(g[y]+dis,f[y])变成g[y]就是上面所说
f[x]就会在f[x]的基础上减去min(g[y]+ w, f[y]) – g[y],那么这个值越大,f[x]就会越小。
f[x]-g[y]就是那个让原本可以到y的,变成不能到y的那条边,f[x]-这条边的最大值,就是g[x]
显然是取最大值,这样g[x]就变得很小
我发个连续的段子,结合图片和f,g数组的定义看,一定可以看得懂
“G[x]的转移有那么一丢丢难想。G[x]一定实在f[x]的基础上,使得某个儿子从不能到达x,变成能到达x,即儿子y对该状态的贡献由min(g[y] + w, f[y])变为g[x].如果这样的话,f[x]就会在f[x]的基础上减去min(g[y]+ w, f[y]) – g[y],那么这个值越大,f[x]就会越小。”
如果实在看不懂,就看看我那含糊不清的理解,说不定,我们心有灵犀,一语点破。
(2)贪心+并查集
思想跟最小生成树一样,简直一模一样
可以通过O(n^2)判断加多一条边是否可以符合题目条件
边从大到小选
如果n大一点,上面的判断可以改成O(m)的,m是边数,根据深度来搜索每一个点。
Code(3)
树形DP①
- uses math;
- var
- n,i,j,x,y,z:longint;
- g,f,e,bz,ok:array[..] of longint;
- b,c:array[..,..] of longint;
- procedure insert(x,y,z:longint);
- begin
- inc(b[x,]);
- b[x,b[x,]]:=y;
- c[x,b[x,]]:=z;
- end;
- procedure dg(x:longint);
- var
- t,i,tt:longint;
- begin
- if ok[x]= then
- begin
- f[x]:=maxlongint;
- for i:= to b[x,] do
- if bz[b[x,i]]= then
- begin
- bz[b[x,i]]:=;
- dg(b[x,i]);
- g[x]:=g[x]+min(g[b[x,i]]+c[x,i],f[b[x,i]]);
- end;
- end
- else
- begin
- t:=;
- for i:= to b[x,] do
- if bz[b[x,i]]= then
- begin
- bz[b[x,i]]:=;
- dg(b[x,i]);
- tt:=min(f[b[x,i]],g[b[x,i]]+c[x,i]);
- f[x]:=f[x]+tt;
- t:=max(t,tt-g[b[x,i]]);
- end;
- g[x]:=f[x]-t;
- end;
- end;
- begin
- assign(input,'s.in');reset(input);
- readln(n);
- for i:= to n- do
- begin
- readln(x,y,z);
- insert(x,y,z);
- insert(y,x,z);
- end;
- while not eof do
- begin
- inc(e[]);
- readln(e[e[]]);
- ok[e[e[]]]:=;
- end;
- bz[]:=;
- dg();
- writeln(min(f[],g[]));
- end.
树形DP②
- const maxn=;
- var i,n,x,y,l,tot:longint;
- yy,next,cost,g,fa,f,gu:array[..maxn] of longint;
- t:array[..maxn] of boolean;
- function max(x,y:longint):longint; begin if x>y then exit(x);exit(y);end;
- function min(x,y:longint):longint; begin if x>y then exit(y);exit(x);end;
- procedure make(x,y,l:longint);
- begin
- inc(tot);
- yy[tot]:=y;
- next[tot]:=gu[x];
- cost[tot]:=l;
- gu[x]:=tot;
- end;
- procedure dfs(x:longint);
- var i,j,sum,y:longint;
- begin
- i:=gu[x];
- sum:=;
- while i<> do begin
- y:=yy[i];
- if fa[x]<>y then begin
- fa[y]:=x;
- dfs(y);
- if t[y] then begin
- f[x]:=f[x]+f[y]+cost[i];
- g[x]:=g[x]+f[y]+cost[i];
- sum:=max(sum,cost[i]);
- end else begin
- f[x]:=f[x]+min(g[y]+cost[i],f[y]);
- if g[y]+cost[i]>f[y] then begin
- sum:=max(sum,f[y]-g[y]);
- g[x]:=g[x]+f[y];
- end else begin
- sum:=max(sum,cost[i]);
- g[x]:=g[x]+g[y]+cost[i];
- end;
- end;
- end;
- i:=next[i];
- end;
- if t[x] then g[x]:=f[x] else g[x]:=g[x]-sum;
- end;
- begin
- readln(n);
- for i:= to n- do begin
- readln(x,y,l);
- make(x+,y+,l);
- make(y+,x+,l);
- end;
- while not eof do begin
- readln(x);
- t[x+]:=true;
- end;
- dfs();
- writeln(min(f[],g[]));
- end.
贪心+并查集
- var
- bz:boolean;
- n,i,j,k,ans:longint;
- f,e,qq:array[..] of longint;
- a:array[..,..] of longint;
- procedure q(l,r:longint);
- var
- i,j,mid:longint;
- begin
- i:=l;
- j:=r;
- mid:=a[(l+r) shr ,];
- while i<j do
- begin
- while a[i,]>mid do inc(i);
- while a[j,]<mid do dec(j);
- if i<=j then
- begin
- a[]:=a[i]; a[i]:=a[j]; a[j]:=a[];
- inc(i); dec(j);
- end;
- end;
- if i<r then q(i,r);
- if l<j then q(l,j);
- end;
- function getfather(x:longint):longint;
- begin
- if f[x]= then exit(x);
- f[x]:=getfather(f[x]);
- exit(f[x]);
- end;
- procedure he(x,y:longint);
- var
- fx,fy:longint;
- begin
- fx:=getfather(x);
- fy:=getfather(y);
- if fx<>fy then
- f[fy]:=fx;
- end;
- begin
- readln(n);
- for i:= to n- do
- begin
- readln(a[i,],a[i,],a[i,]);
- inc(a[i,]);
- inc(a[i,]);
- end;
- while not eof do
- begin
- inc(e[]);
- readln(e[e[]]);
- inc(e[e[]]);
- end;
- q(,n-);
- for i:= to n- do
- begin
- qq:=f;
- if getfather(a[i,])<>getfather(a[i,]) then
- he(a[i,],a[i,]);
- bz:=true;
- for j:= to e[] do
- for k:= to e[] do
- if j<>k then
- if getfather(e[j])=getfather(e[k]) then
- bz:=false;
- if not bz then
- begin
- f:=qq;
- inc(ans,a[i,])
- end;
- end;
- writeln(ans);
- end.
[jzoj]1729.blockenemy的更多相关文章
- [BZOJ3223]Tyvj 1729 文艺平衡树
[BZOJ3223]Tyvj 1729 文艺平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区 ...
- BZOJ3223: Tyvj 1729 文艺平衡树 [splay]
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3595 Solved: 2029[Submit][Sta ...
- BZOJ 3223: Tyvj 1729 文艺平衡树
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3628 Solved: 2052[Submit][Sta ...
- zoj 3673 1729
1729 Time Limit: 3 Seconds Memory Limit: 65536 KB 1729 is the natural number following 1728 and ...
- bzoj 3223/tyvj 1729 文艺平衡树 splay tree
原题链接:http://www.tyvj.cn/p/1729 这道题以前用c语言写的splay tree水过了.. 现在接触了c++重写一遍... 只涉及区间翻转,由于没有删除操作故不带垃圾回收,具体 ...
- hdoj 1729 Stone Games(SG函数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1729 看了题目感觉像Nim,但是有范围限制,有点不知道SG函数该怎么写 看了题解,最后才明白该怎么去理 ...
- bzoj3223 Tyvj 1729 文艺平衡树(Splay Tree+区间翻转)
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2202 Solved: 1226[Submit][Sta ...
- BZOJ 3223: Tyvj 1729 文艺平衡树(splay)
速度居然进前十了...第八... splay, 区间翻转,用一个类似线段树的lazy标记表示是否翻转 ------------------------------------------------- ...
- 3223: Tyvj 1729 文艺平衡树
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1347 Solved: 724[Submit][Stat ...
随机推荐
- 虚拟机下安装Centos7并配置Apache+PHP+Mysql+phpmyadmin+wordpress
一.安装Apache yum install httpd 安装成功后,Apache操作命令: systemctl start httpd //启动apache systemctl stop httpd ...
- STL容器之优先队列
STL容器之优先队列 优先级队列,以前刷题的时候用的比较熟,现在竟然我只能记得它的关键字是priority_queue(太伤了).在一些定义了权重的地方这个数据结构是很有用的. 先回顾队列的定义:队列 ...
- ubuntu中vim下按上下左右键时输入A、B、C、D
ubuntu系统自带的 vi 不完整导致,解决方法:安装完整的vi $ sudo apt-get install vim-gtk 1. 为root用户设置密码 sudo passwd root 需要先 ...
- exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused
1.虽然,不是大错,还说要贴一下,由于我运行run-example streaming.NetworkWordCount localhost 9999的测试案例,出现的错误,第一感觉就是Spark没有 ...
- OpenJDK-study-002 从GitHub下载openjdk,以及Cygwin的安装
承前启后 由于上一篇openjdk-study-001中,从Mercurial直接拉取openjdk森林失败,于是网上搜了一下,发现GitHub上有人分享openjdk的源码 https://gith ...
- bzoj 松鼠的新家
哈夫曼距离与切比雪夫距离的转化
- [转]PyCharm安装及使用
https://www.jianshu.com/p/042324342bf4 PyCharm 搭建环境 1.win10_X64,其他Win版本也可以. 2.PyCharm版本:Professional ...
- C# 之 提高WebService性能大数据量网络传输处理
1.直接返回DataSet对象 特点:通常组件化的处理机制,不加任何修饰及处理: 优点:代码精减.易于处理,小数据量处理较快: 缺点:大数据量的传递处理慢,消耗网络资源: 建议:当应用系统在内网.专网 ...
- linux重启服务的脚本命令
最近做网站测试,每次测试完成都要重启服务,为此写了一个简单的shell脚本 linux服务重启shell脚本示例 2014年12月18日 linux服务重启脚本,如何实现linux服务的定时重启,可以 ...
- python模块安装查看、包制作
一. 模块安装 ubuntu : apt-get install python-pip redhat: yum install python-pip pip install 模块 pip instal ...