题目大意

给你n个点的坐标和权值

问先在每一行选一个点再在每一列选一个没选过的点

求最大权值和

分析

可以想到将点转化为边,将两个坐标对应两个点

所以问题转化为选H+W个边

使得所有边的度都不为0

则最终这个图就会变为若干联通块

每个个联通块正好有一个环

我们将边权从大到小排序

然后并查集维护一下联通块信息和是否正好包含一个环即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
struct node {
    int x,y,w;
};
node d[200100];
int n,m,H,W,fa[200100],is[200100];
long long Ans;
inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
inline bool cmp(const node a,const node b){return a.w>b.w;}
signed main(){
    int i,j,k;
    scanf("%lld%lld%lld",&m,&H,&W);
    n=H+W;
    for(i=1;i<=n;i++)fa[i]=i;
    for(i=1;i<=m;i++){
      scanf("%lld%lld%lld",&d[i].x,&d[i].y,&d[i].w);
      d[i].y+=H;
    }
    sort(d+1,d+m+1,cmp);
    for(i=1;i<=m;i++){
      int x=d[i].x,y=d[i].y;
      if(sf(x)!=sf(y)){
          if(is[sf(x)]&&is[sf(y)])continue;
          is[sf(y)]|=is[sf(x)];
          fa[sf(x)]=sf(y);
          Ans+=d[i].w;
      }else {
          if(!is[sf(x)]){
            is[sf(x)]=1;
            Ans+=d[i].w;
          }
      }
    }
    printf("%lld\n",Ans);
    return 0;
}