TopCoder SRM 612 DIV 1 450 SpecialCells

题意:

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));
		}
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值