相對水的一道樹形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;
}
}