用一个最小值和最大值来表示每个节点的范围,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&>[u]<v)gt[u]=v; 19 if(r==1&<[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 }