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 } 
  • 相关阅读:
    头文件里面的ifndef /define/endif的作用
    互联网小知识
    IT技术开发人员获得成功的六大步骤
    ab网站压力测试
    微软校招试题
    C程序编译过程浅析
    makefile变量赋值
    printf的题目
    Oracle命名规范
    javascript(js)小数精度丢失的解决方案
  • 原文地址:https://www.cnblogs.com/LI-dox/p/11229546.html
Copyright © 2011-2022 走看看