1. 程式人生 > 實用技巧 >2020牛客多校第八場I題 Interesting Computer Game(並查集+判環)

2020牛客多校第八場I題 Interesting Computer Game(並查集+判環)

題意:給出n對元組<a, b>每次可以選擇a或者b或者不選,問最多可以選擇出多少種不同的數字。n<1e5, a,b<1e9

題解:把數字離散化化成點,存在<a,b>則a,b之間加邊,對於一個聯通分量,如果含有環則對答案的貢獻是sz,否則是sz-1。注意:這題有一個離散化,開並查集陣列的時候應該開雙倍,初始化也是同樣,還有就是別忘記了合併的時候有一方已經含有環的情況。

#include <bits/stdc++.h>
#define IO_read ios::sync_with_stdio(false);cin.tie(0)
#define fre freopen("C:\\in.txt", "r", stdin)
#define
_for(i,a,b) for(int i=a; i< b; i++) #define _rep(i,a,b) for(int i=a; i<=b; i++) #define inf 0x3f3f3f3f #define lowbit(a) ((a)&-(a)) using namespace std; typedef long long ll; template <class T> void read(T &x) { char c; bool op=0; while(c=getchar(), c<'0'||c>'9') if(c=='
-') op=1; x=c-'0'; while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0'; if(op) x=-x; } const int maxn=2e5+5; //段錯誤一次 int T, n, kase, a[maxn], b[maxn], c[maxn]; int fa[maxn], having[maxn], sz[maxn]; int find_fa(int x) { if(fa[x]==x) return x; return fa[x]=find_fa(fa[x]); }
int main() { read(T); while(T--) { read(n); //_rep(i, 1, n) fa[i]=i, sz[i]=1, having[i]=0; WA了一次 _rep(i, 1, n) read(a[i]), read(b[i]), c[2*i-1]=a[i], c[2*i]=b[i]; sort(c+1, c+1+2*n); int cnt=unique(c+1, c+1+2*n)-c-1; _rep(i, 1, cnt) fa[i]=i, sz[i]=1, having[i]=0; _rep(i, 1, n){ a[i]=lower_bound(c+1, c+1+cnt, a[i])-c; b[i]=lower_bound(c+1, c+1+cnt, b[i])-c; } _rep(i, 1, n){ int f1=find_fa(a[i]), f2=find_fa(b[i]); if(f1!=f2){ fa[f2]=f1, sz[f1]+=sz[f2]; if(having[f2]) having[f1]=1; //這裡漏寫了 } else{ having[f1]=1; } } int ans=0; _rep(i, 1, cnt) if(find_fa(i)==i) ans+=sz[i]-1+having[i]; printf("Case #%d: %d\n", ++kase, ans); } return 0; }