并查集【p2700】逐个击破
题目描述-->p2700 逐个击破
题意概括
花费最小的代价,使得一些有标记的节点不连通.
分析
我们需要花费最小代价使得原来连通的图中一些节点之间不相互连通.
贪心显然是可行的(一点也不显然
看到其他人写了dp,写了贪心.
但我感觉可以排序+并查集做啊.
排序
考虑我们要花费最小代价删边,但是并查集不支持删除操作.
(貌似有一种东西叫分治线段树可以维护这种操作.
因此,我们根据容斥原理(这玩意是叫容斥吧.
花费最小代价删边,等价于花最大代价建边,最后剩下不建的边,就是我们的答案.
所以说,我们需要按照边权从大到小建图。sort!
我们需要保证的是两个敌人节点不互相连通.
这就是我们并查集的作用!
并查集
首先明确:
并查集要初始化,一定要初始化!
下面的图中,红色代表敌人节点,绿色代表我方节点.
如果某两个节点是我们的敌人节点,我们一定不会去建边.(为虎作伥? 像这样↓.
如果你连接,那你就违背了题目要求,你也不是一个
秉承伟大军事家的战略思想,一个有智慧的军长了
还有,如果我们已经将敌人包围建出下面这样的图这时,还有一个敌人节点.↓
如果我们连接某一个我方节点,不连接敌方节点,那敌人也会互相连接(翻过屋后的山
所以说我们需要考虑一下如何解决这种情况.
如果,我方节点已经连接了敌方节点,则需要标记我方节点,使得敌方节点无法通过我方节点连接敌方节点.
因此说,我们可以把连接到敌人节点的我方节点变成敌人节点.
从而使得其他敌人节点与其无法连接.
那我们上面的图就变成这样↓
这样我们的程序就可以实现我们所想了.
最后我们会将边权大的边加入到并查集中.
则最后没有加入到并查集中的点,就会是被孤立的敌方节点.
所以我们把总边权减去我们加入到图中的边权就是我们的ans啦!
关于样例
样例建的原图↓
最终是这样的↓
因此我们在样例的答案是4.
--------------------代码---------------------
#include<bits/stdc++.h>
#define IL inline
#define RI register int
IL void in(int &x)
{
int f=1;x=0;char s=getchar();
while(s>'9' or s<'0'){if(s=='-')f=-1;s=getchar();}
while(s>='0' and s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,k,f[100008],tot;
bool init[1000008];
long long ans;
struct cod{int u,v,w;}edge[100008];
IL int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
IL bool ccp(const cod&a,const cod&b){return a.w>b.w;}
int main(void)
{
in(n),in(k);
for(RI i=1;i<=n;i++)f[i]=i;//一定要初始化!
for(RI i=1,x;i<=k;i++)in(x),init[x]=true;
for(RI i=1;i<=n-1;i++)
in(edge[i].u),in(edge[i].v),in(edge[i].w),ans+=edge[i].w;
std::sort(edge+1,edge+n,ccp);//从大到小sort.
for(RI i=1;i<=n-1;i++)
{
int u=edge[i].u,v=edge[i].v,w=edge[i].w;
int fu=find(u),fv=find(v);
if(init[fu] and init[fv])continue;
f[fu]=fv;
ans-=w;//减去边
if(init[fu])init[fv]=true;
else if(init[fv])init[fu]=true;
}
printf("%lld",ans);
}
并查集【p2700】逐个击破的更多相关文章
- P2700逐个击破(并查集/树形dp)
P2700 逐个击破 题目背景 三大战役的平津战场上,傅作义集团在以北平.天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜.为了就地歼敌不让其逃走,老毛同志 ...
- 洛谷P2700 逐个击破
P2700 逐个击破 题目背景 三大战役的平津战场上,傅作义集团在以北平.天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜.为了就地歼敌不让其逃走,毛主席制 ...
- 洛谷 P2700 逐个击破
P2700 逐个击破 题目背景 三大战役的平津战场上,傅作义集团在以北平.天津为中心,东起唐山西至张家口的铁路线上摆起子一字长蛇阵,并企图在溃败时从海上南逃或向西逃窜.为了就地歼敌不让其逃走,毛主席制 ...
- Luogu P2700 逐个击破
qwq 同关押罪犯 对于这种希望几个对象分开的题目,只要把并查集反过来想就可以了. 既然要求删除的边权最小,那么只要反过来求给定的点不连通时保留的边权最大即为正解. 同样的,首先将边权排序,不会使敌人 ...
- P2700 逐个击破 最小生成树
题目描述 现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的,现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这 ...
- P2700 逐个击破
题意:现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的, 现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少的代价将这K ...
- LuoguP2700逐个击破【并查集/生成树/正难则反】By cellur925
题目传送门 题目大意:给你一棵树,求把其中k个点相互隔离(不连通)所需要的边权代价. 这题我开始是想要求出把k个点联通的最小代价的,但后来发现还是实现起来比较困难,题解里貌似也没有这种做法,于是就鸽了 ...
- 【题解】逐个击破 luogu2700
题目 题目描述: 现在有N个城市,其中K个被敌方军团占领了,N个城市间有N-1条公路相连,破坏其中某条公路的代价是已知的. 现在,告诉你K个敌方军团所在的城市,以及所有公路破坏的代价,请你算出花费最少 ...
- HDU 4496 D-City(并查集,逆思维)
题目 熟能生巧...常做这类题,就不会忘记他的思路了... //可以反过来用并查集,还是逐个加边,但是反过来输出...我是白痴.....又没想到 //G++能过,C++却wa,这个也好奇怪呀... # ...
随机推荐
- hdu 6057 Kanade's convolution(子集卷积)
题解: 然后就是接下来如何fwt 也就是如何处理bit(x) - bit(y) = bit(k)这个条件. 其实就是子集卷积. 把bit(x)和bit(y)划分成两个集合,然后就是子集卷积的形式. 这 ...
- [洛谷P1278]单词游戏
题目大意:给一个有$n(n\leqslant16)$个单词的字典,求单词接龙的最大长度 题解:发现$n$很小,可以状压,令$f_{i,j}$表示选的数的状态为$i$,最后一个字母是$j$的最大长度. ...
- AdjustTokenPrivileges启用权限
原文链接地址:http://blog.csdn.net/xbgprogrammer/article/details/7276760 我们有很多操作需要用到OpenProcess函数,而为了使程序 ...
- BZOJ1103 [POI2007]大都市meg 【树剖】
1103: [POI2007]大都市meg Time Limit: 10 Sec Memory Limit: 162 MB Submit: 3038 Solved: 1593 [Submit][S ...
- 【ZJ选讲·钻石游戏】
N×M的棋盘(M,N<=500)中,每个格子有一个颜色(颜色数1~9) P次操作(P<=1000),每次给出两个相邻的位置(保证颜色不同,两个格子有一条公共边),把这两个格子交换. 定 ...
- 【CF MEMSQL 3.0 E. Desk Disorder】
time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...
- android脱壳之DexExtractor原理分析
导语: 上一篇我们分析android脱壳使用对dvmDexFileOpenPartial下断点的原理,使用这种方法脱壳的有2个缺点: 1. 需要动态调试 2. 对抗反调试方案 为了提高工作效率, ...
- ubuntu安装GraphicsMagick
一. sudo apt-get install graphicsmagick 二. http://www.cnblogs.com/cocowool/archive/2010/08/16/1800954 ...
- Spring学习--泛型依赖注入
暂时没有搞懂.
- java+ssh+eclipse开发过程问题记录
原文 http://www.sdfengxi.com/?p=408 最近在忙着的项目是基于cloudstack平台的管理平台,因为CloudStack使用java开发,管理机上已部署好rhel+t ...