zoukankan      html  css  js  c++  java
  • Chemistry in Berland CodeForces

    题目

    题意:

    有n种化学物质,第i种物质现有bi千克,需要ai千克。有n-1种,编号为2-n的转换方式,每种都为(x,k),第i行是编号为i+1的转换方式,编号为i的转换方式(xi,ki)表示ki千克的xi物质可以转换成1千克的i物质,1千克的i物质可以转换成1千克的xi物质。问是否可能通过转换得到足够的需要的物质。(1 ≤ xj + 1 ≤ j)

    重点:上面标红的条件。如果只保留ki千克的xi物质可以转换成1千克的i物质产生的一条有向边,表明xi物质连出的边一定是指向编号大于i的物质的(x[i+1]<=i,x[i]<=i-1,x[i]<i),而又恰好有n-1条边,也就是这种情况下这是一棵树

    方法:建树,dfs自底向上递推(我用的方法是只保留ki千克的xi物质可以转换成1千克的i物质产生的一条xi->i的有向边),如果某样物质不够就从父结点那儿转换,如果某样物质多了就把多的转换成父结点的物质。(如果父结点的物质不够,直接减就行,减成负数也没关系)

    奇怪的地方:貌似这道题极限数据会爆longlong,然后直接在爆longlong的时候判为NO就行?

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #define inf 110000000000000000
     4 typedef long long LL;
     5 struct Edge
     6 {
     7     LL to,dis,next;
     8 }edge[100100];
     9 LL n,num_edge;
    10 LL first1[100100];
    11 LL a[100100],b[100100];
    12 double tem;
    13 void dfs(LL x,LL fa,LL p)
    14 {
    15     LL k=first1[x];
    16     while(k!=0)
    17     {
    18         dfs(edge[k].to,x,edge[k].dis);
    19         k=edge[k].next;
    20     }
    21 //    if(a[x]<b[x])
    22 //        b[fa]+=b[x]-a[x];
    23 //    else if(a[x]>b[x])
    24 //        b[fa]-=p*(a[x]-b[x]);
    25     if(a[x]<b[x])
    26         b[fa]+=b[x]-a[x];
    27     else if(a[x]>b[x])
    28     {
    29         tem=(double)(b[x]-a[x])*p;//为何要double?
    30         if(tem<-inf)
    31         {
    32             printf("NO");
    33             exit(0);
    34         }
    35         b[fa]-=p*(a[x]-b[x]);
    36         if(b[fa]<-inf)
    37         {
    38             printf("NO");
    39             exit(0);
    40         }
    41     }
    42 }
    43 int main()
    44 {
    45     LL i,x,k;
    46     scanf("%lld",&n);
    47     for(i=1;i<=n;i++)
    48         scanf("%lld",&b[i]);
    49     for(i=1;i<=n;i++)
    50         scanf("%lld",&a[i]);
    51     for(i=2;i<=n;i++)
    52     {
    53         scanf("%lld%lld",&x,&k);
    54         edge[++num_edge].to=i;
    55         edge[num_edge].dis=k;
    56         edge[num_edge].next=first1[x];
    57         first1[x]=num_edge;
    58     }
    59     k=first1[1];
    60     while(k!=0)
    61     {
    62         dfs(edge[k].to,1,edge[k].dis);
    63         k=edge[k].next;
    64     }
    65     if(b[1]<a[1])
    66         printf("NO");
    67     else
    68         printf("YES");
    69     return 0;
    70 }
  • 相关阅读:
    2018-10-20-WPF-通过位处理合并图片
    2019-2-11-WPF-获取应用的所有窗口
    2019-2-11-WPF-获取应用的所有窗口
    2018-8-10-WPF-如何在绑定失败异常
    2018-8-10-WPF-如何在绑定失败异常
    类和对象
    类和对象
    什么是可串行化MVCC
    LeetCode-环形链表|+环形链表||
    用js仿探探拖拽卡片的效果、飞卡片的效果,感觉挺酷,最后有美女看哦!
  • 原文地址:https://www.cnblogs.com/hehe54321/p/cf-846e.html
Copyright © 2011-2022 走看看