qoj10536 Card Flipping
题意
给出 \(n\) 组二元组 \((a_i,b_i)\),从每组二元组中选出一个元素,使得不同元素数量最多。
\(n\le 2\times 10^5,a_i,b_i\le 10^6\)。
思路
网络流秒了。
多开 \(n\) 个点存每组二元组,源点连这 \(n\) 个点,每个点连 \(a_i,b_i\),每个元素连到汇点,流量均为 \(1\)。
可以发现这是一个二分图,时间复杂度 \(O(n\sqrt{n})\),可以通过。
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
namespace mf{
const int N=1200005,INF=0x3f3f3f3f;
struct node{
int x,w,rev;
};
vector<node> t[N];
int dep[N],gap[N],maxflow;
int n,S,T;
void init(int nn){
for(int i=1;i<=nn+2;i++)
t[i].clear();
n=nn+2,S=nn+1,T=nn+2;
}
void add(int x,int y,int w){
t[x].push_back({y,w,t[y].size()});
t[y].push_back({x,0,t[x].size()-1});
}
void bfs(){
memset(gap,0,sizeof(gap));
memset(dep,-1,sizeof(dep));
queue<int> q;
q.push(T),dep[T]=0,gap[dep[T]]++;
while(!q.empty()){
int u=q.front();q.pop();
for(node v:t[u])
if(!~dep[v.x])
dep[v.x]=dep[u]+1,gap[dep[v.x]]++,q.push(v.x);
}
}
int dfs(int x,int flow){
if(x==T) return maxflow+=flow,flow;
int used=0;
for(auto&[v,w,rev]:t[x]){
if(w&&dep[v]+1==dep[x]){
int mn=dfs(v,min(w,flow-used));
if(mn) w-=mn,t[v][rev].w+=mn,used+=mn;
if(flow==used) return used;
}
}
gap[dep[x]]--;
if(!gap[dep[x]]) dep[S]=n+1;
dep[x]++,gap[dep[x]]++;
return used;
}
int isap(){
maxflow=0;
bfs();
if(dep[S]==-1) return 0;
while(dep[S]<n) dfs(S,INF);
return maxflow;
}
}
int n,a[200005],b[200005];
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>n;
mf::init(1e6+1+n);
for(int i=1;i<=n;i++) cin>>a[i],a[i]++;
for(int i=1;i<=n;i++) cin>>b[i],b[i]++;
for(int i=1;i<=n;i++)
mf::add(mf::S,1000001+i,1),mf::add(1000001+i,a[i],1),mf::add(1000001+i,b[i],1);
for(int i=1;i<=1000001;i++)
mf::add(i,mf::T,1);
cout<<mf::isap();
return 0;
}

浙公网安备 33010602011771号