题目
题意:给出n个二元组,每组只能选一个数,问最多选几个数。
可以先进行并查集将这些数分成很多树或者圈,相当于一条边连接两个点,我们只能选择其中一点,树可以选n-1个点,圈可以选n个点。
数大n小,可以离散化。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int N=200005;
int f[N];
bool circle[N];
int getf(int u){
if(f[u]==u)return u;
return f[u]=getf(f[u]);
}
void merge(int u,int v){
int t1=getf(u);
int t2=getf(v);
if(t1!=t2){
f[t1]=t2;
circle[t2]|=circle[t1];
}
else circle[t1]=true;
}
unordered_map<ll,int> mp;
int main(){
int T,n;
scanf("%d",&T);
int cas=1;
while(T--){
scanf("%d",&n);
ll u,v;
memset(circle,false,sizeof(circle));
for(int i=0;i<N;i++)f[i]=i;
mp.clear();
int cnt=0;
for(int i=1;i<=n;i++){
scanf("%lld%lld",&u,&v);
if(!mp[u]){
mp[u]=++cnt;
}
if(!mp[v]){
mp[v]=++cnt;
}
merge(mp[u],mp[v]);
}
int ans=cnt;
for(int i=1;i<=cnt;i++){
if(f[i]==i&&!circle[i])ans--;
}
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}
网络最大流直接做,每个二元组之间建一条边。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#define ll long long
using namespace std;
const int NN = 2e6+5;
const int INF = 0x3f3f3f3f;
const int N=200005;
typedef pair<int,int> PII;
typedef unsigned long long ull;
int he[NN], ne[NN], ver[NN], e[NN], l[NN];
int tot,n;
vector<int> v,node[N];
void init()
{
memset(he, 0, sizeof(he));
for(int i=0;i<N;i++){
node[i].clear();
}
tot = 1;
v.clear();
}
void add(int x, int y, int w)
{
e[++tot] = w;
ver[tot] = y;
ne[tot] = he[x];
he[x] = tot;
e[++tot] = 0;
ver[tot] = x;
ne[tot] = he[y];
he[y] = tot;
}
bool bfs(int s, int t)
{
memset(l, 0, sizeof(l));
queue<int> q;
q.push(s);
l[s] = 1;
while(q.size())
{
int x = q.front();
q.pop();
if (x == t) return 1;
for (int i = he[x]; i; i = ne[i])
{
int y = ver[i];
if (!l[y] && e[i])
{
l[y] = l[x] + 1;
q.push(y);
}
}
}
return 0;
}
int dfs(int x, int MaxFlow, int t)
{
if (x == t) return MaxFlow;
int uflow = 0;
for (int i = he[x]; i; i = ne[i])
{
int y = ver[i];
if (l[y] == l[x] + 1 && e[i])
{
int flow = min(e[i], MaxFlow - uflow);
flow = dfs(y, flow, t);
e[i] -= flow;
e[i^1] += flow;
uflow += flow;
if (uflow == MaxFlow)
break;
}
}
if (uflow == 0)
l[x] = 0;
return uflow;
}
int Dinic(int s, int t)
{
int MaxFlow = 0;
while(bfs(s, t))
MaxFlow += dfs(s, INF, t);
return MaxFlow;
}
int get_id(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int main()
{
int T;
scanf("%d",&T);
PII a[N];
int cas=1;
while(T--){
scanf("%d",&n);
init();
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].first,&a[i].second);
v.push_back(a[i].first);
v.push_back(a[i].second);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;i++){
int u=get_id(a[i].first);
int v=get_id(a[i].second);
node[u].push_back(v);
}
int s=N,t=N-1;
for(int i=1;i<=v.size();i++){
add(s,i,1);
for(int j=0;j<node[i].size();j++){
add(i,node[i][j],1);
add(node[i][j],t,1);
}
}
int ans = Dinic(s,t);
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}