AT_jsc2019_qual_e Card Collector

首先考虑什么情况不合法。假设 \(S\) 为选出卡片的集合,玩一下发现不合法当且仅当存在 \(T\subseteq S\)\(X=\{x|(x,y)\in T\}\)\(Y=\{y|(x,y)\in T\}\) 满足 \(|X|+|Y|<|T|\)

假设当前需要加入一个点 \((x_i,y_i)\) 考虑限制。发现这个对于任意集合很不好做,于是考虑最严格的限制。

对于 \(S\) 中的 \((x,y)\)

  1. \(x\in X,y\notin Y\)\(x\notin X,y\in Y\),加入 \(T\) 一定不劣。

  2. \(x\in X,y\in Y\),加入 \(T\) 一定不劣。

  3. \(x\notin X,y\notin Y\),不加入 \(T\) 一定不劣。

于是每选入卡片 \((x,y)\),将行 \(x\) 向列 \(y\) 连边。\((x,y)\) 能选入的条件为:

  1. \(B_x=B_y\)\(e_{B_x}<|B_x|\)

  2. \(B_x\ne B_y\)\(e_{B_x}+e_{B_y}<|B_x|+|B_y|\)

其中 \(B_i\)\(i\) 所在的连通块,\(e_i\) 为连通块 \(i\) 中的边数。

按照价值降序排序后,每个卡片换掉之前已经选入的卡片一定不优,所以直接贪心即可。

#include<bits/stdc++.h>
#define fin(x) freopen(#x".in","r",stdin)
#define fout(x) freopen(#x".out","w",stdout)
#define fr(x) fin(x),fout(x);
#define Fr(x,y) fin(x),fout(y)
#define INPUT(_1,_2,FILE,...) FILE
#define IO(...) INPUT(__VA_ARGS__,Fr,fr)(__VA_ARGS__)
using namespace std;
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cfast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define ll long long
#define ull unsigned long long
#define intz(x,y) memset((x),(y),sizeof((x)))
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
#define tup(x) array<int,(x)>
inline ll read(){
    ll x=0,f=1;char ch=nc();
    while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
    while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
   	return x*f;
}
const int N=2e6+5;
int b[N<<1],tot,f[N<<2],siz[N<<2],ct[N<<2];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
struct node{int x,y;ll v;}a[N];
inline void UesugiErii(){
	int n,r,c;cin>>n>>r>>c;
	for(int i=1;i<=n;i++)
		cin>>a[i].x>>a[i].y>>a[i].v;
	sort(a+1,a+1+n,[](node x,node y){return x.v>y.v;});
	ll s=0,cnt=0,res=0;
	for(int i=1;i<=r+c;i++)f[i]=i,siz[i]=1;
	for(int i=1;i<=n;i++){
		int X=a[i].x,Y=a[i].y,x=find(X),y=find(Y+r);
		if(ct[x]<siz[x]||ct[y]<siz[y]){
			if(x!=y)
				f[x]=y,siz[y]+=siz[x],ct[y]+=ct[x];
			++ct[y],res+=a[i].v;
		}
	}
	cout<<res;
}
signed main(){
	cfast;
	int _=1;//cin>>_;
	for(;_;_--)UesugiErii();
	return 0;
}
posted @ 2025-11-17 19:42  Uesugi1  阅读(3)  评论(0)    收藏  举报