题意:
A选中二维平面上一些点,将x和y分别排序后发给B,B据此猜测原来的点集,问至少能猜对几个?当然一次猜测中同一个点不会出现两次。
题解:
费用流,所有的x和所有的y连边,若(xi,yj)并不是原来的点,则费用为0,否则费用为1
//import java.io.File;
//import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.*;
class _edge
{
int v,c,w,nex;
public void Init(int _to,int _con,int _fee,int _nex)
{
v=_to;
c=_con;
w=_fee;
nex=_nex;
}
}
class pair
{
int a,b;
public pair(int _a,int _b)
{
a=_a;
b=_b;
}
}
public class SpecialCells
{
final static int MAXN = 110;
final static int MAXM = MAXN*MAXN;
boolean []vi=new boolean[MAXN];
int []fee=new int[MAXN],con=new int [MAXN],fa=new int [MAXN];
int []he=new int [MAXN];
int top;
static _edge []ed=new _edge[MAXM];
static
{
for(int i=0;i<MAXM;++i)
{
ed[i]=new _edge();
}
}
ArrayList<pair> int2pair(int arr[])
{
ArrayList<pair> list=new ArrayList<>();
Arrays.sort(arr);
for(int i=0,j=-1;i<arr.length;++i)
if(i==0||list.get(j).a!=arr[i])
{
list.add(new pair(arr[i],1));
++j;
}
else ++list.get(j).b;
return list;
}
void addEdge(int u,int v,int con,int w)
{
ed[top].Init(v, con,w, he[u]);
he[u]=top++;
ed[top].Init(u, 0, -w, he[v]);
he[v]=top++;
}
int SPFA(int s,int t)
{
int ret=0;
for(int i=0;i<=t;++i)
{
vi[i]=false;
fee[i]=Integer.MAX_VALUE;
con[i]=Integer.MAX_VALUE;
fa[i]=-1;
}
Queue<Integer> que=new LinkedList<Integer>();
que.offer(s);
fee[s]=0;
vi[s]=true;
while(que.size()!=0)
{
s=que.poll();
vi[s]=false;
for(int i=he[s];i!=-1;i=ed[i].nex)
{
int v=ed[i].v,c=Math.min(ed[i].c, con[s]);
if(c>0&&fee[v]>fee[s]+c*ed[i].w)
{
fee[v]=fee[s]+c*ed[i].w;
con[v]=c;
fa[v]=i;
if(!vi[v])
{
vi[v]=true;
que.offer(v);
}
}
}
}
if(fee[t]==Integer.MAX_VALUE) return Integer.MIN_VALUE;
ret=fee[t];
int now=fa[t];
while(now!=-1)
{
ed[now].c-=con[t];
ed[now^1].c+=con[t];
now=fa[ed[now^1].v];
}
return ret;
}
int LFMF(int s,int t)
{
int ret=0,tmp;
while((tmp=SPFA(s,t))!=Integer.MIN_VALUE)
ret+=tmp;
return ret;
}
public int guess(int a[],int b[])
{
int len=a.length;
for(int i=0;i<len*2;++i)
he[i]=-1;
top=0;
TreeMap<Integer,TreeSet<Integer> > ma=new TreeMap<Integer,TreeSet<Integer>>();
for(int i=0;i<len;++i)
{
if(ma.containsKey(a[i])==false)
ma.put(a[i], new TreeSet<Integer>());
ma.get(a[i]).add(b[i]);
}
ArrayList<pair> arr=int2pair(a),brr=int2pair(b);
int s1=arr.size(),s2=brr.size();
for(int i=0;i<s1;++i)
for(int j=0;j<s2;++j)
{
int c=arr.get(i).a,d=brr.get(j).a;
if(ma.get(c).contains(d)==false)
addEdge(i+1,j+1+s1,1,0);
else addEdge(i+1,j+1+s1,1,1);
}
for(int i=0;i<s1;++i)
addEdge(0,i+1,arr.get(i).b,0);
for(int i=0;i<s2;++i)
addEdge(i+1+s1,s1+s2+1,brr.get(i).b,0);
return LFMF(0,s1+s2+1);
}
public static void main(String []args) throws FileNotFoundException
{
Scanner scan=new Scanner(System.in);
//InputStream in=new FileInputStream(new File("/home/moor/Code/input"));
//Scanner scan=new Scanner(in);
SpecialCells spe=new SpecialCells();
while(scan.hasNext())
{
int n=scan.nextInt();
int []a=new int [n],b=new int[n];
for(int i=0;i<n;++i)
a[i]=scan.nextInt();
for(int i=0;i<n;++i)
b[i]=scan.nextInt();
System.out.println(spe.guess(a, b));
}
}
}