LuoguP2700逐个击破【并查集/生成树/正难则反】By cellur925

题目传送门

题目大意:给你一棵树,求把其中k个点相互隔离(不连通)所需要的边权代价。



这题我开始是想要求出把k个点联通的最小代价的,但后来发现还是实现起来比较困难,题解里貌似也没有这种做法,于是就鸽了。但是大体的思考方向还是不直接去想把k个点隔离,而是把问题转化。

花费最小代价删边->花费最大代价建边。而建边的时候如果遇到一条两边都是敌人的边,我们显然是不需要建的,所以这其实我们需要维护敌人的网络,用并查集来维护。

首先我们标记敌人点,再把边从大到小排序。枚举所有的边,如果它两端点都是敌人,那肯定不连他。如果两端点有一个是敌人,也连上,并在那个无辜的点上打一个标记,因为之后的点也不能再连他。于是我们就可以用并查集维护。最后注意我们之后调用的都是这个集合的代表元,即getf。

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define maxn 100090
 4
 5 using namespace std;
 6 typedef long long ll;
 7
 8 int n,k;
 9 ll ans;
10 int vis[maxn],fa[maxn];
11 struct node{
12     int to,from,val;
13 }edge[maxn*2];
14
15 bool cmp(node a,node b)
16 {
17     return a.val>b.val;
18 }
19
20 int getf(int x)
21 {
22     if(fa[x]==x) return x;
23     return getf(fa[x]);
24 }
25
26 int main()
27 {
28     scanf("%d%d",&n,&k);
29     for(int i=1;i<=k;i++)
30     {
31         int x=0;
32         scanf("%d",&x);
33         vis[x]=1;
34     }
35     for(int i=1;i<=n-1;i++)
36         scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val),ans+=edge[i].val;
37     for(int i=1;i<=n;i++) fa[i]=i;
38     sort(edge+1,edge+1+n-1,cmp);
39     for(int i=1;i<=n-1;i++)
40     {
41         int pp=getf(edge[i].from),qq=getf(edge[i].to);
42         if(vis[pp]&&vis[qq]) continue;
43         ans-=edge[i].val;
44         if(qq!=pp) fa[qq]=pp;
45         if(vis[pp]) vis[qq]=1;
46         else if(vis[qq]) vis[pp]=1;
47     }
48     printf("%lld",ans);
49     return 0;
50 }

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9744089.html

时间: 2024-08-30 02:55:53

LuoguP2700逐个击破【并查集/生成树/正难则反】By cellur925的相关文章

luoguP2700 逐个击破

发现自己又做了一道水题 这真的是蓝题吗? 思路和关押罪犯一样 当您A了这道题后,您可以顺利A掉luoguP1525(祝您成功 (不是很明白为什么关押罪犯就是绿题而逐个击破是蓝题 (我觉得关押罪犯更难啊orz emmmm 正如青青姐所说,这种题要反着想 先将边从大到小排 用color数组标记一下是敌方还是己方(一开始打成了基房orz 如果是敌方就标为true 再从最大的边开始连 如果两个点都是true,显然不行,就跳过,继续下一次循环 如果只有一个点是敌方,就把两个点连到一个并查集里,以便下一次查

树上统计treecnt(dsu on tree 并查集 正难则反)

题目链接 \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\(L\sim R\)号点两两连通,最少需要选择的边的数量. 求\[\sum_{l=1}^n\sum_{r=l}^nTree[l,r]\] \(Solution\) 枚举每条边,计算它的贡献. 那么我们要判断有多少连续区间的点跨过这条边,并不好算,反过来去求在这条边的两侧分别有多少个连续区间. 那么显然有\(O(n^2)\)的做法,即对每条边DFS它的两侧,枚

HDU 4786 Fibonacci Tree 并查集+生成树=kruskal

Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2149    Accepted Submission(s): 682 Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him t

51nod 1050 循环数组最大子段和【环形DP/最大子段和/正难则反】

1050 循环数组最大子段和 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题  收藏  关注 N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列).当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13.和为20. Input 第1

CF 1005B Delete from the Left 【模拟数组操作/正难则反】

You are given two strings s and t. In a single move, you can choose any of two strings and delete the first (that is, the leftmost) character. After a move, the length of the string decreases by 1. You can't choose a string if it is empty. For exampl

并查集&amp;MST

[HDU] 1198 Farm Irrigation 基础最小生成树★ 1598 find the most comfortable road 枚举+最小生成树★★ 1811 Rank of Tetris 并查集+拓扑排序★★ 3926 Hand in Hand 同构图★ 3938 Portal 离线+并查集★★ 2489     Minimal Ratio Tree dfs枚举组合情况+最小生成树★ 4081     Qin Shi Huang's National Road System 最

CF109 C. Lucky Tree 并查集

Petya loves lucky numbers. We all know that lucky numbers are the positive integers whose decimal representations contain only the lucky digits 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not. One day Petya encountered a tre

cdoj 1328 卿学姐与诡异村庄 Label:并查集 || 二分图染色

卿学姐与诡异村庄 Time Limit: 4500/1500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 日复一日,年复一年,春去秋来. 卿学姐终于从天行廖那里毕业啦.出山的卿学姐首先来到了一个诡异的村庄. 在这个村庄中,只有两种人,一种是好人,一种是坏人. 好人只说真话,坏人只说假话. 村庄虚伪的平静由于卿学姐的到来,终于被打破了. 人们开始互相指控,每个人都会说另外一个人是否是好人.

ACM学习历程—Hihocoder 1291 Building in Sandbox(dfs &amp;&amp; 离线 &amp;&amp; 并查集)

http://hihocoder.com/problemset/problem/1291 前几天比较忙,这次来补一下微软笔试的最后一题,这题是这次微软笔试的第四题,过的人比较少,我当时在调试B题,没时间看这一题.不过打过之前一场BestCoder的应该都会有点思路,虽然BC那题是二维,这题是三维的,但是思路应该是一样的,没错,就是离线加并查集. 正过来考虑的时候,发现第一个要求相邻块是好处理的,但是第二个要求能否到达(1000, 1000, 1000)这个条件似乎比较难判断,当时BC上的题根据题