{题解}[jzoj1729]blockenemy
来源:互联网 发布:乐乎网络电话 编辑:程序博客网 时间:2024/06/09 20:53
jzoj1729
Description
你在玩电子游戏的时候遇到了麻烦。。。。。。 你玩的游戏是在一个虚拟的城市里进行,这个城市里有n个点,都从0~n-1编了号,每两个点之间有且仅有一条路径。现在,你的敌人到这个城市来踩点了!!!为了阻止他们更好的踩点, 你决定切断他们所有踩点人员的联系,使他们孤军作战,然后在各个击破。但是这就要切断某些街道,而你每切断一条路,市民就会产生相对的不满值,不满值越大,城市的和谐度就越小。所以你现在需要知道为了使踩点人员所在的点两两之间不联通所切断的边产生的最小不满值是多少?
额,使树上m个点不联通的最小代价?就这么理解罢。
Idea
着实吓人,但事实上也不怎么可怕。
不多讨论部分分了,直接考虑100%的数据
有两种不错的方法。
Ⅰ树形DP
由于这个方法没有成功融会贯通,所以只好贴别人的。
不过我并不推荐树形DP。
确乎有些小题大做
不会Ⅱ贪心(+并查集)?
没有关系,我们还有法Ⅲ
Ⅲ贪心+LCA
这是由Couzit黄靖元提供的方法。
显然,这是一棵树,所以任意两点的路径是唯一的。
我们考虑
为使
若不考虑其他的点,我们必定是选择边权最小的边删去,显然的局部最优。
稍加思索,我们发现对于整个图(全局),这也是最优的!
因此,我们只需枚举相连通的两点,删去路径上最短边即可。
可以用
很蹊跷,不是吗?
有没有可能
我们可以尝试举一个反例。
红色点为踩点人员所在点
如果我们删去权值为3的边,是不是更优呢?然而并不是的。
不要为你的双眼所蒙蔽,如果我们删去权值为3的边,左子树的两点是联通的!
再意会意会,这种贪心策略的正确性是保证的。
最重要的,这种方式码量极少!
Code
法Ⅰ
const maxn=500;var i,n,x,y,l,tot:longint; yy,next,cost,g,fa,f,gu:array[1..maxn] of longint; t:array[1..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:=0; while i<>0 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:=1 to n-1 do begin readln(x,y,l); make(x+1,y+1,l); make(y+1,x+1,l); end; while not eof do begin readln(x); t[x+1]:=true; end; dfs(1); writeln(min(f[1],g[1]));end.
法Ⅱ
#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>using namespace std;const int N = 55;int n,ans;int h[N],flag[N];struct node{ int x,y,z;} a[N];bool cmp(node A,node B){return A.z>B.z;}int gf(int x){ if (x!=h[x]) h[x] = gf(h[x]); return h[x];}bool link(int x,int y){ int i = gf(x),j = gf(y); if (flag[i] && flag[j]) return 0; else { h[i] = j; flag[j] |= flag[i]; } return 1;}int main(){ scanf("%d",&n); for (int i=1;i<n;i ++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); int x; while (scanf("%d",&x)!=EOF) flag[x] = 1; for (int i=1;i<=n;i ++) h[i] = i; sort(a+1,a+n,cmp); for (int i=1;i<n;i ++) if (!link(a[i].x,a[i].y)) ans += a[i].z; printf("%d\n",ans); return 0;}
法Ⅲ
const maxn=50; maxm=50;var n,tot:longint; i,j,l:longint; fx,fy:longint; ans,min:longint; numx,numy:longint; bz:array[0..maxn] of boolean; fa,q,dep:array[0..maxn] of longint; a,map:array[0..maxn,0..maxn] of longint;procedure dfs(x,deep:longint);var i:longint;begin if(bz[x])then exit; bz[x]:=true;dep[x]:=deep; for i:=1 to a[x][0] do if(not bz[a[x][i]])then begin fa[a[x][i]]:=x; dfs(a[x][i],deep+1); end;end;procedure init;var i,j:longint; x,y,c:longint;begin fillchar(map,sizeof(map),$7f); readln(n); for i:=1 to n-1 do begin readln(x,y,c); inc(a[x][0]);a[x][a[x][0]]:=y; inc(a[y][0]);a[y][a[y][0]]:=x; map[x][y]:=c;map[y][x]:=c; end; fa[0]:=0; while(not seekeof)do begin inc(tot); readln(q[tot]); end;end;procedure swap(var a,b:longint);var c:longint;begin c:=a;a:=b;b:=c;end;begin init(); dfs(0,1); for i:=1 to tot-1 do begin for j:=i+1 to tot do begin min:=maxlongint; fx:=q[i];fy:=q[j]; if(dep[fx]<dep[fy])then swap(fx,fy); while(dep[fx]>dep[fy])do begin if(map[fx,fa[fx]]<min)then begin min:=map[fx,fa[fx]]; numx:=fx; numy:=fa[fx]; end; fx:=fa[fx]; end; while(fx<>fy)do begin if(map[fx,fa[fx]]<min)then begin min:=map[fx,fa[fx]]; numx:=fx; numy:=fa[fx]; end; if(map[fy,fa[fy]]<min)then begin min:=map[fy,fa[fy]]; numx:=fy; numy:=fa[fy]; end; fx:=fa[fx];fy:=fa[fy]; end; inc(ans,min); map[numx,numy]:=0;map[numy,numx]:=0; end; end; writeln(ans); close(input);close(output);end.
3 0
- {题解}[jzoj1729]blockenemy
- JZOJ1729. blockenemy
- jzoj1729 blockenemy(贪心,并查集)
- blockenemy
- blockenemy
- blockenemy
- 1729. blockenemy
- JZOJ.1729. blockenemy
- jozj. 1729.blockenemy
- 1729. blockenemy (Standard IO)
- JZOJ 1729. blockenemy
- JZOJ 7.9 B组第二题 blockenemy
- [jzoj]1729. blockenemy(树形DP+详细分析)
- 题解
- 题解
- 题解
- 题解
- 题解
- java由出生日期算出年龄
- Docker的一些操作
- Java基础_内部类、静态内部类、成员内部类、局部内部类、匿名内部类 (转)
- 二叉树
- ThinkPHP 3.2.3 简单后台模块开发(一)常用配置
- {题解}[jzoj1729]blockenemy
- HBase介绍
- java常用设计模式趣解
- 如何免费下载高程数据并生成TIF文件
- 如何去掉MyEclipse中的MyEclipse Derby
- 今天的我更加愚蠢了呢
- jQuery中的DOM和CSS操作
- 洛谷 P1082 [NOIP2012 D2T1] 同余方程
- 引用路径的注意点