HDU 4274 spy work (树形DP)
相对水的一道树形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; } }