思路:
-
题意:一共有N个回合,每回合提供两个整数ai和bi,只能选以下三个操作之一。
- 不做任何操作。
- 如果ai没被选过,可以选择ai。
- 如果bi没被选过,可以选择bi。
先给出所有回合的数,求出选择的最多整数数量。
-
直接用一个并查集来解决这个问题。
-
如果ai和bi的父亲一样(即堆中有环),我们就用数组来记录这里的父亲(父亲一直在变,所以这里先数组记录,后面再找这个父亲的父亲解决问题);
-
否则,我们将 ai 与 bi 合并,计算每个堆里有多少个不同的元素。
-
答案就是每个堆中元素(不重复)的个数,如果一个堆里没有环就再减1。
代码实现: 代码还有点问题,明天再debug了吧
#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ll long long
#define int long long
#define pii pair<int, int>
#define lowbit(x) (x &(-x))
#define ls(x) x<<1
#define rs(x) (x<<1+1)
#define me(ar) memset(ar, 0, sizeof ar)
#define mem(ar,num) memset(ar, num, sizeof ar)
#define rp(i, n) for(int i = 0, i < n; i ++)
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define pre(i, n, a) for(int i = n; i >= a; i --)
#define IOS ios::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int way[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
using namespace std;
const int inf = 0x7fffffff;
const double PI = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1e9 + 7;
const int N = 1e5 + 5;
int T, n;
int a[N], b[N], c[N << 1], f[N << 1];
map<int,int> mp;
int find(int x)
{
if(f[x] != x) f[x] = find(f[x]);
return f[x];
}
signed main()
{
cin >> T;
for(int cnt = 1; cnt <= T; cnt ++){
int t = 0; mp.clear();
cin >> n;
for(int i = 0; i < n; i ++){
cin >> a[i] >> b[i];
if(!mp[a[i]]) mp[a[i]] = ++t;
if(!mp[b[i]]) mp[b[i]] = ++t;
}
for(int i = 1; i <= t; i ++) c[i] = 0, f[i] = i;
for(int i = 0; i < n; i ++){
int x = find(mp[a[i]]);
int y = find(mp[b[i]]);
if(x != y){
f[x] = y;
if(c[x] || c[y]) c[y] = 1, c[x] = 0;
}
else c[y] = 1;
}
int ans = t;
for(int i = 1; i <= t; i ++)
if(f[i] == i && !c[i]) ans --;
printf("Case #%d: %d\n", cnt, ans);
}
return 0;
}