zoukankan      html  css  js  c++  java
  • 【洛谷P2700】【JZOJ2936】逐个击破【并查集】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P2700
    给出一棵树和几个标记点,每条边有权值,求割掉其中几条边,使得这几个标记点互不相连。求割掉的边的最小代价和。


    思路:

    蒟蒻忘了KruskalKruskal,不知道这种方法是不是KruskalKruskal
    我们要割掉边权和最小的几条边其实就是保留最大的边权和的边。
    p[i]p[i]表示第ii个点是否是标记点。
    然后读入的每条边都用单向边储存。将边全部按权值大到小排序。
    枚举每条边。设这条边的两个节点分别是uuvv,那么如果p[find(u)]!=1p[find(v)]!=1(!(p[find(u)]&p[find(v)]))p[find(u)]!=1||p[find(v)]!=1(其实就是!(p[find(u)]\&p[find(v)])),那么就可以连这条边。那么这两个集合就合二为一,如果原来第二个集合是有标记点的,那么第一个集合的父亲就肯定要标为有标记点。即
    p[find(u)]=p[find(v)]p[find(u)]|=p[find(v)]
    然后ansans加上这条边的权值即可。
    最终答案就是总权值ans-ans


    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #define N 100100
    #define ll long long
    using namespace std;
    
    int n,m,father[N],head[N],tot;
    bool p[N];
    ll ans,sum;
    
    struct edge
    {
    	int next,to,c,from;
    }e[N];
    
    void add(int from,int to,int c)
    {
    	e[++tot].to=to;
    	e[tot].from=from;
    	e[tot].c=c;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    bool cmp(edge x,edge y)
    {
    	return x.c>y.c;
    }
    
    int find(int x)  //寻找祖先(路径压缩)
    {
    	return x==father[x]?x:father[x]=find(father[x]);
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int x,y,z;
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d",&x);
    		p[x+1]=1;  //标记点
    	}
    	for (int i=1;i<n;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		add(x+1,y+1,z);
    		sum+=(ll)z;  //总权值
    	}
    	sort(e+1,e+n,cmp);
    	for (int i=1;i<=n;i++)
    	 father[i]=i;
    	for (int i=1;i<n;i++)
    	 if (!(p[find(e[i].from)]&p[find(e[i].to)]))  //不能两边都是标记点
    	 {
    	 	ans+=(ll)e[i].c;
    	 	p[find(e[i].from)]|=p[find(e[i].to)];
    	 	father[find(e[i].to)]=father[find(e[i].from)];  //合二为一
    	 }
    	cout<<sum-ans;
    	return 0;
    }
    
  • 相关阅读:
    hdu 2485 Destroying the bus stations 迭代加深搜索
    hdu 2487 Ugly Windows 模拟
    hdu 2492 Ping pong 线段树
    hdu 1059 Dividing 多重背包
    hdu 3315 My Brute 费用流,费用最小且代价最小
    第四天 下载网络图片显示
    第三天 单元测试和数据库操作
    第二天 布局文件
    第一天 安卓简介
    Android 获取存储空间
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998515.html
Copyright © 2011-2022 走看看