码迷,mamicode.com
首页 > 其他好文 > 详细

【USACO 2017 December Gold】A Pie for a Pie 题解

时间:2020-06-01 21:06:28      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:line   完成   ESS   strong   优化   continue   模型   text   for   

思路

首先注意到题目中的几个性质:

  1. 不会送出同一个 \(\pi\) ,题目不允许,而且也不可能是最优方案。
  2. 如果送出某个 \(\pi\) (除了第一个),那么刚刚收到的 \(\pi\) 肯定是固定的某个 \(\pi\)

那么基于此,设 \(B_i\) 为Bessie做的第 \(i\)\(\pi\) 的答案、 \(E_i\) 为Elsie做的第 \(i\)\(\pi\) 的答案,我们可以设出转移方程:

\(f_i=\begin{cases}1&\text{如果Elsie的评价为0}\\\min{\{E_j\}}&\text{如果Elsie对当前}\pi\text{的评价}\leq\text{对Elsie做的第}j\text{个}\pi\text{的评价}\end{cases}\)

\(E_i=\begin{cases}1&\text{如果Bessie的评价为0}\\\min{\{F_j\}}&\text{如果Bessie对当前}\pi\text{的评价}\leq\text{对Bessie做的第}j\text{个}\pi\text{的评价}\end{cases}\)

明显的(也就想了我半个小时),这是一个最短路的模型,所以我们把Bessie做的 \(\pi\) 设成 \(1\)~\(n\) 号点,把Elsie做的 \(\pi\) 设成 \(n+1\)~\(n+n\) 号点,然后建图,然后跑最短路即可。

实现

建图明显是 \(n^2\) 的(其实本来就是 \(n^2\) 的,但是数据……),考虑优化至\(n\log{n}\),有两种方法:

  1. 把Bessie做的 \(\pi\) 按Bessie的评价排序,把Elsie做的 \(\pi\) 按Elsie的评价排序。

    对于一个Bessie做的 \(\pi\) ,用二分找到最小可以让Elsie送出哪个 \(\pi\) ,然后一个一个建边直到不能建边为止。对于Elsie做的 \(\pi\) 同理。

  2. 把所有的 \(\pi\) copy一份放在另一个数组里,然后Bessie的 \(\pi\) 分别按Bessie的评价和Elsie的评价排序。对于Elsie做的 \(\pi\) 同理。

    对于一个Bessie做的 \(\pi\) ,用另一个只增不减的指针找到最小可以让Elsie送出哪个 \(\pi\) ,然后再用一个循环一个一个建边直到不能建边为止。对于Elsie做的 \(\pi\) 同理。

注意:连边时要反着连,然后再构造一个源点连到每一个“出口”的点(即 \(F_i\)\(E_i\) 为1的点)。并不需要特殊处理答案,对于一个点只要有一个0就可以认为是“出口”(数据过水)。

然后建图就完成了,跑最短路即可。

Code

Warning:建边部分可能引起不适,请谨慎观看

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,w[200010],a[200010][2],cb[2][100010],ce[2][100010],last,h[200010],b[1500010][2],d[200010];
bool bz[200010];
void read(int &x){
	char c=getchar();
	for(;c<33;c=getchar());
	for(x=0;(47<c)&&(c<58);x=x*10+c-48,c=getchar());
}
bool comp1(int x,int y){
	return(a[x][0]<a[y][0]);
}
bool comp2(int x,int y){
	return(a[x][1]<a[y][1]);
}
void add(int x,int y){
	b[++last][0]=h[x];
	b[last][1]=y;
	h[x]=last;
}
void spfa(){
	int dh=0,dt=1;
	memset(w,127,sizeof(w));
	w[0]=0;
	while(dh<dt){
		for(int i=h[d[++dh]];i;i=b[i][0]){
			if(w[b[i][1]]>w[d[dh]]+1){
				w[b[i][1]]=w[d[dh]]+1;
				if(!bz[b[i][1]]){
					d[++dt]=b[i][1];
					bz[b[i][1]]=1;
				}
			}
		}
		bz[d[dh]]=0;
	}
}
int main(){
	freopen("piepie.in","r",stdin);
	freopen("piepie.out","w",stdout);
	read(n);read(m);
	for(int i=1;i<=n;i++){
		read(a[i][0]);read(a[i][1]);
		cb[0][i]=cb[1][i]=i;
	}
	for(int i=1;i<=n;i++){
		read(a[i+n][0]);read(a[i+n][1]);
		ce[0][i]=ce[1][i]=i+n;
	}
	sort(cb[0]+1,cb[0]+n+1,comp1);
	sort(cb[1]+1,cb[1]+n+1,comp2);
	sort(ce[0]+1,ce[0]+n+1,comp1);
	sort(ce[1]+1,ce[1]+n+1,comp2);
	for(int i=1,j=1;i<=n;i++){
		for(;a[cb[1][i]][1]>a[ce[1][j]][1]&&j<=n;j++);
		if(a[cb[1][i]][1]==0){
			add(0,cb[1][i]);
			continue;
		}
		for(int k=j;a[cb[1][i]][1]+m>=a[ce[1][k]][1]&&k<=n;add(ce[1][k],cb[1][i]),k++);
	}
	for(int i=1,j=1;i<=n;i++){
		for(;a[ce[0][i]][0]>a[cb[0][j]][0]&&j<=n;j++);
		if(a[ce[0][i]][0]==0){
			add(0,ce[0][i]);
			continue;
		}
		for(int k=j;a[ce[0][i]][0]+m>=a[cb[0][k]][0]&&k<=n;add(cb[0][k],ce[0][i]),k++);
	}
	spfa();
	for(int i=1;i<=n;i++){
		printf("%d\n",w[i]==0x7f7f7f7f?-1:w[i]);
	}
	fclose(stdin);
	fclose(stdout);
	return(0);
}

【USACO 2017 December Gold】A Pie for a Pie 题解

标签:line   完成   ESS   strong   优化   continue   模型   text   for   

原文地址:https://www.cnblogs.com/groundwater/p/13027194.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!