zoukankan      html  css  js  c++  java
  • 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
    ",dis[i]);
    92     return 0;
    93 } 
  • 相关阅读:
    CSUFT 1002 Robot Navigation
    CSUFT 1003 All Your Base
    Uva 1599 最佳路径
    Uva 10129 单词
    欧拉回路
    Uva 10305 给任务排序
    uva 816 Abbott的复仇
    Uva 1103 古代象形文字
    Uva 10118 免费糖果
    Uva 725 除法
  • 原文地址:https://www.cnblogs.com/LI-dox/p/11229546.html
Copyright © 2011-2022 走看看