HDU 4274 Spy's Work (树形DP,模拟)

 

 

题意: 

  给定一棵树,每个节点代表一个员工,节点编号小的级别就小,那么点1就是boss了。接下来给出对m个点的限制,有3种符号分别是op=“大于/小于/等于”,表示以第i个点为根的子树所有人的工资之和 大于/小于/等于 x,要求判断m个限制是否冲突了。注意每个员工的工资下限是1,而无上限。ps:可能出现对同个点多个限制,注意取交集。

 

 

思路:

  很水的题嘛,想复杂了。注意限制是针对整棵子树的!所以我们只需要算出这棵子树的范围,再判断是否和所给的限制有冲突,如果没有冲突的话还得取“所给限制”与“计算出的范围”的交集。在输入m个限制的时候注意可能已经冲突了,需先提前判断一下。注意可能需要用longlong,初始化时就将每个人的范围限制在[1,INF),这样就完事了~

 

 

  1 //#include <bits/stdc++.h>
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <map>
  7 #include <deque>
  8 #include <algorithm>
  9 #include <vector>
 10 #include <iostream>
 11 #define pii pair<int,int>
 12 #define max(x,y) ((x)>(y)?(x):(y))
 13 #define min(x,y) ((x)<(y)?(x):(y))
 14 #define INF 0x7f7f7f7f
 15 #define LL  long long
 16 using namespace std;
 17 const double PI  = acos(-1.0);
 18 const int N=10100;
 19 bool isWA;
 20 int n, edge_cnt, head[N];
 21 LL down[N], up[N];
 22 struct node
 23 {
 24     int from, to, next;
 25     node(){};
 26     node(int from,int to,int next):from(from),to(to),next(next){};
 27 }edge[N];
 28 
 29 void add_node(int from,int to)
 30 {
 31     edge[edge_cnt]=node(from,to,head[from]);
 32     head[from]=edge_cnt++;
 33 }
 34 
 35 bool DFS(int t)
 36 {
 37     node e;
 38     LL L=1, R=INF;        //计算此子树的范围
 39     for(int i=head[t]; i!=-1; i=e.next)
 40     {
 41         e=edge[i];
 42         if(DFS(e.to)==false)    return false;
 43         L+=down[e.to];
 44     }
 45 
 46     if(head[t]==-1)    //叶子,只要在[1,INF)都是合法的
 47     {
 48         if(up[t]>0)  return true;
 49         else         return false;
 50     }
 51     else
 52     {
 53         if( R<down[t] || L>up[t]  )    return false;    //无交集
 54         down[t]=max(down[t], L);        //更新本子树的范围
 55         up[t]=min(up[t], R);
 56         return true;
 57     }
 58 }
 59 
 60 
 61 void init(int n)
 62 {
 63     for(int i=0; i<=n; i++) //注意初始化问题
 64         down[i]=1,
 65         up[i]=INF,
 66         head[i]=-1;
 67     isWA=false;
 68     edge_cnt=0;
 69 }
 70 
 71 int main()
 72 {
 73     //freopen("input.txt", "r", stdin);
 74     int n, m, a, d;char b,c;
 75     while(~scanf("%d",&n))
 76     {
 77         init(n);
 78         for(int i=2; i<=n; i++)
 79         {
 80             scanf("%d",&a);
 81             add_node(a,i);
 82         }
 83         scanf("%d",&m);
 84 
 85         for(int i=0,L,R; i<m; i++)
 86         {
 87             scanf("%d%c%c%d",&a,&b,&c,&d);
 88             L=1, R=INF;
 89             if(c=='<')         R=d-1;
 90             else if(c=='>')    L=d+1;
 91             else               L=R=d;
 92             if(L>up[a] || R<down[a])  isWA=true;//所给条件可能已经冲突
 93             down[a]=L, up[a]=R;
 94         }
 95         if(!isWA && DFS(1))  puts("True");
 96         else                 puts("Lie");
 97     }
 98 
 99     return 0;
100 }
AC代码

 

转载于:https://www.cnblogs.com/xcw0754/p/4836380.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值