Description
Solution
方法一:
每个属性向物品连边,二分图跑匈牙利匹配。
方法二:
设每个物品的属性为((x,y))且(x<y),让这个物品贡献属性(x),然后让原来贡献(x)的物品去贡献(z),其中(z)是贡献(x)的物品所能贡献的另一个属性,用并查集维护。
Code
一:
#include <cstdio>
#include <cstring>
typedef long long ll;
const int N = 1000010;
const int M = 2000010;
int matchL[N], matchR[N], hd[N], to[M], nxt[M], cnt, vis[N];
inline void adde(int x, int y) {
to[++cnt] = y;
nxt[cnt] = hd[x];
hd[x] = cnt;
}
bool dfs(int x) {
for (int i = hd[x]; i; i = nxt[i]) {
if (vis[to[i]] != x) {
vis[to[i]] = x;
if (!matchL[to[i]] || dfs(matchL[to[i]])) {
matchL[to[i]] = x;
matchR[x] = to[i];
return true;
}
}
}
return false;
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1, x, y; i <= n; ++i) {
scanf("%d%d", &x, &y);
if (x <= n) adde(x, i);
if (y <= n) adde(y, i);
}
int i = 1;
for (; i <= n; ++i) {
if (matchR[i]) continue;
if (!dfs(i)) break;
}
printf("%d
", i-1);
return 0;
}
二:
#include <algorithm>
#include <cstdio>
#include <cstring>
typedef long long ll;
const int N = 1000010;
const int M = 2000010;
int fa[N], vis[N];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < N; ++i) fa[i] = i;
for (int i = 1, x, y; i <= n; ++i) {
scanf("%d%d", &x, &y);
x = find(x), y = find(y);
if (x == y)
vis[x] = 1;
else {
if (x > y) std::swap(x, y);
if (vis[x])
vis[y] = 1;
else
vis[x] = 1;
fa[x] = y;
}
}
for (int i = 1; i <= n; ++i)
if (!vis[i]) {
printf("%d
", i-1);
return 0;
}
printf("%d
", n);
return 0;
}