USACO 2017 December Contest Gold T1: A Pie for a Pie

Posted li-dox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USACO 2017 December Contest Gold T1: A Pie for a Pie相关的知识,希望对你有一定的参考价值。

题目大意

Bessie和Elsie各自烤了 N(1≤N≤10^5)个馅饼。Bessie 会这 2N 个馅饼打分,Elsie 也会。二者的打分均为一个 1e9 的非负整数。由于她们口味不同,每个派的两个分数可能不同。
她们想互赠礼物。开始时,Bessie 送给 Elsie 一个馅饼。她们收到礼物(对方做的馅饼)后都会回赠对方一个自己做的馅饼。
她们选择回礼的方法相同。以 Elsie 为例,Elsie 根据自己的打分来选择回礼。回礼的分数至少要大于她收到的馅饼的分数,但两个馅饼的分数差不能大于 D(0≤D≤10^9) 。如果有多个馅饼满足要求,Elsie 可以选择其中的任意一个作为回礼。

若没有馅饼满足要求,Elsie 会放弃。Bessie 选择回礼的方法同理。
她们之间的礼物交换将持续到一头牛放弃(Bad End),或一头牛收到一个她自己打分为 0 的馅饼,此时礼物交换愉快结束(Happy End)。
请注意,不能把一个馅饼赠送两次,不能把馅饼送给自己。
Bessie 想知道:对于每个她做的馅饼,如果她将这个馅饼作为最开始送给 Elsie 的礼物,她俩至少要互赠多少次馅饼(Bessie 给 Elsie 算一次,Elsie 回赠 Bessie 又算一次),才能 Happy End 。如果不可能 Happy End,请输出 -1

题目分析

我们要求出对于每个馅饼,都要求出最少要送多少次。而观察数据范围,显然一个一个求是不太可行的,所以考虑一次全求出来,使用最短路。

考虑如何建边,我们应该反向建边,把每个分数0的点作为起点。建图时应对每个两人的pie分别排序,这样便于二分建图。

(虽然此算法可能被卡成N2 的,但由于出题人都是懒的,所以可以通过)

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=400005;
 4 const int Inf=0x3f3f3f3f;
 5 struct Node
 6     int bv,ev,id;
 7 pb[MAXN],pe[MAXN];
 8 
 9 inline bool cmpb(Node x,Node y)
10     return x.bv<y.bv;
11 
12 inline bool cmpe(Node x,Node y)
13     return x.ev<y.ev;
14 
15 struct FboB
16     inline bool operator()(const Node &x,const Node &y)
17         return x.bv<y.bv;
18     
19 ;
20 struct FboE
21     inline bool operator()(const Node &x,const Node &y)
22         return x.ev<y.ev;
23     
24 ;
25 
26 struct Edge
27     int to,nxt;
28 e[MAXN<<4];
29 int cnt,head[MAXN<<1];
30 inline void add_edge(int u,int v)
31     e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
32 
33 int n,d;
34 queue<int> q;
35 int dis[MAXN<<1];
36 inline void bfs()
37     while(!q.empty())
38         int x=q.front();
39         q.pop();
40         for(int i=head[x],y;i;i=e[i].nxt)
41             y=e[i].to;
42             if(dis[y]!=-1) continue;
43             dis[y]=dis[x]+1;
44             q.push(y);
45         
46     
47 
48 int main()
49     memset(dis,-1,sizeof(dis));
50     scanf("%d%d",&n,&d);
51     for(int i=1;i<=n;++i)
52         scanf("%d%d",&pb[i].bv,&pb[i].ev);
53         if(pb[i].ev==0)
54             dis[i]=1;
55             q.push(i);
56         
57         pb[i].id=i;
58     
59     for(int i=1;i<=n;++i)
60         scanf("%d%d",&pe[i].bv,&pe[i].ev);
61         if(pe[i].bv==0)
62             dis[i+n]=1;
63             q.push(i+n);
64         
65         pe[i].id=i+n;
66     
67     sort(pb+1,pb+n+1,cmpb);
68     sort(pe+1,pe+n+1,cmpe);
69     for(int i=1,pos;i<=n;++i)
70         Node tmp;
71         tmp.bv=pe[i].bv;
72         tmp.ev=pe[i].bv;
73         pos=lower_bound(pb+1,pb+n+1,tmp,FboB())-pb;
74         for(int j=pos;j<=n;++j)
75             if(pb[j].bv>pe[i].bv+d) break;
76             add_edge(pb[j].id,pe[i].id);
77         
78     
79     for(int i=1,pos;i<=n;++i)
80         Node tmp;
81         tmp.bv=pb[i].ev;
82         tmp.ev=pb[i].ev;
83         pos=lower_bound(pe+1,pe+n+1,tmp,FboE())-pe;
84         for(int j=pos;j<=n;++j)
85             if(pe[j].ev>pb[i].ev+d) break;
86             add_edge(pe[j].id,pb[i].id);
87         
88     
89     bfs();
90     for(int i=1;i<=n;++i)
91         printf("%d\n",dis[i]);
92     return 0;
93  

 

以上是关于USACO 2017 December Contest Gold T1: A Pie for a Pie的主要内容,如果未能解决你的问题,请参考以下文章

USACO 2017 December Contest Platinum T2: Push a Box

USACO 2017 December Contest Platinum T3: Greedy Gift Takers

USACO 2017 December Contest Gold T1: A Pie for a Pie

USACO 2016 December Contest Gold T1: Moocast

USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法

USACO 2018 December Contest Platinum T2: Sort It Out