HDU 4274 Spy's Work [DFS]

   用一个最小值和最大值来表示每个节点的范围,DFS一遍即可。父亲节点的最小值必然比儿子节点的最小值之和大1(它自身至少要1元),至于最大值,没有什么限制,我一开始一直WA在这里了,因为儿子最大值的和是限制不了父亲节点的,因为父亲节点可以取任意大的值。。最后每个节点的最小值都一定小于等于最大值才会是正确的。。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #define MAXN 10005
 4 typedef long long LL;
 5 const LL INF=100000000000LL;
 6 struct edge{
 7     int v,n;
 8 }e[MAXN];
 9 //gt[u]<=val[u]<=lt[u]
10 LL gt[MAXN],lt[MAXN],tv;
11 int first[MAXN],es;
12 int n,m,tu,flag;
13 char op[5];
14 void addedge(int u,int v){
15     e[es].v=v,e[es].n=first[u],first[u]=es++;
16 }
17 void merge(int u,LL v,int r){
18     if(r==0&&gt[u]<v)gt[u]=v;
19     if(r==1&&lt[u]>v)lt[u]=v;
20     if(gt[u]>lt[u])flag=0;
21 }
22 int dfs(int u){
23     LL gtv=0,ltv=0;
24     int in=1;
25     for(int i=first[u];i!=-1;i=e[i].n){
26         in+=dfs(e[i].v);
27         gtv+=gt[e[i].v],ltv+=lt[e[i].v];
28     }
29     if(in!=1)merge(u,gtv+1,0),merge(u,INF,1);
30     else merge(u,1,0);
31     return in;
32 }
33 int main(){
34     while(scanf("%d",&n)!=EOF){
35         memset(first,-1,sizeof first);es=0;
36         for(int i=1;i<=n;i++)gt[i]=0,lt[i]=INF;
37         for(int i=2;i<=n;i++){
38             scanf("%d",&tv);
39             addedge(tv,i);
40         }
41         scanf("%d",&m);
42         flag=1;
43         for(int i=1;i<=m;i++){
44             scanf("%d%s%I64d",&tu,op,&tv);
45             if(op[0]=='>')merge(tu,tv+1,0);
46             if(op[0]=='<')merge(tu,tv-1,1);
47             if(op[0]=='=')merge(tu,tv,0),merge(tu,tv,1);
48         }
49         if(flag)dfs(1);
50         printf(flag?"True\n":"Lie\n");
51     }
52     return 0;
53 }

 

原文地址:https://www.cnblogs.com/swm8023/p/2679491.html