相对水的一道树形DP,把父子关系想清楚了就容易多了
题意:给出一部分节点的信息,问你这部分信息有没有冲突。大致题意。详细自己看。
解题思路:我的想法是给通过两个数组表示各个节点的上下限,如果上限小于下限,那么这是冲突的,上限==下限,表明这点的工资是确定的。
先输入各种关系,然后一遍DFS即可。我们得明白一件事,儿子只能够修改父亲的下限,不能修改父亲的上限
#include<iostream>
#include<stdio.h>
#include<string.h>
#define LL long long
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int maxn=10005;
struct edge
{
int u,v,next;
}e[maxn<<1];
int tot,head[maxn],n,m;
LL upper[maxn],lower[maxn];
bool vis[maxn],conflict;
void add_edge(int u,int v);
void dfs(int root);
int main()
{
int a,i,b;
LL B;
char re;
while(cin>>n)
{
memset(head,-1,sizeof(head));
tot=0;
for(i = 2;i <= n; i++)
{
a=i;
cin >> b;
add_edge(a,b);
add_edge(b,a);
}
memset(upper,-1,sizeof(upper));//上限为-1,表示不确定
for(i=1;i<=n;i++)
lower[i]=1;
cin >> m;
for(i = 1;i <= m; i++)
{
scanf("%d %c %lld",&a,&re,&B);
if(re == '=') upper[a]=lower[a]=B;
else if(re == '>') lower[a]=B+1;
else upper[a]=B-1;
}
conflict=false;
memset(vis,false,sizeof(vis));
dfs(1);
if(conflict)
puts("Lie");
else puts("True");
}
return 0;
}
void add_edge(int u,int v)
{
e[tot].u=u,e[tot].v=v;
e[tot].next=head[u],head[u]=tot++;
}
void dfs(int root)
{
if(vis[root]||conflict) return ;
vis[root] = true;
if(upper[root]!=-1&&upper[root]<lower[root]) //先判断每个节点自身是否有矛盾
{
conflict=true;
return ;
}
int i,nexti;
LL lo;
bool leaf=true;
lo=0;
for(i=head[root];i!=-1;i=e[i].next)
{
nexti=e[i].v;
if(!vis[nexti])
{
leaf=false;
dfs(nexti);
lo+=lower[nexti];//统计儿子下限
}
}
if(leaf) return ;
lo++;
lower[root]=max(lo,lower[root]);//更新父亲的下限
if(upper[root]!=-1&&lower[root]>upper[root])//检测冲突
{
conflict=true;
}
}