• Forsaken喜欢独一无二的树


    题意描述

    题目链接

    开始想法:

    开始的想法是图中一个环内,如果最大的两条边相同,那么就应该删除其中一条;做法是:
    (1)将边从小到大排序,之后并查集合并x,y;
    (2)用p[fx]维护并查集最大的边;
    (3)如果fx==fy且当前边权值w==p[fx],说明应该删除这条边
    这个想法是错误,这个在并查集上最大的边不一定在环上
    

    核心:

    看了别人是这样做的
    (1)将边从大到小排序
    (2)对于相同权值的边统一考虑,若这条边上两点不连通开始全部加入ans中;然后在考虑重复加入的情况,也是逐渐加入这些权值相同的边,若两点不连通ans-=w; 否则说明这条边不唯一,应该删去
    

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=2e5+7;
    struct node{
    	int x,y;
    	int w;
    	bool operator<(const node& a) const {
    		return w<a.w;
    	}
    };
    node e[N];
    int fa[N];
    int n,m;
    LL ans=0;
    int find_fa(int x) {
    	if(fa[x]!=x)
    		fa[x]=find_fa(fa[x]);
    	return fa[x];
    }
    int main()
    {
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=m;i++)	scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].w);
    	for(int i=1;i<=n;i++)	fa[i]=i;
    	sort(e+1,e+1+m);
    	for(int i=1;i<=m;) {
    		int w=e[i].w;
    		int j=i;
    		while(j<=m&&e[j].w==w) j++;
    		for (int k=i;k<j;k++) {
    			int fx=find_fa(e[k].x);
    			int fy=find_fa(e[k].y);
    			if(fx!=fy)
    				ans+=w;
    		}
    		for (int k=i;k<j;k++) {
    			int fx=find_fa(e[k].x);
    			int fy=find_fa(e[k].y);
    			if(fx!=fy) {
    				fa[fx]=fy;
    				ans-=w;
    			}
    		}
    		i=j;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    格式化输出数字
    传教士经验
    集合
    替换
    连接
    填充
    取值
    分割
    创建日历和日期列表
    常用日期格式
  • 原文地址:https://www.cnblogs.com/xidian-mao/p/11761160.html
Copyright © 2020-2023  润新知