#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h>
#define N 6005 //树形dp POJ2342
using namespace std;
struct tree
{
int child, father, brother; //结点的子节点,父亲结点, 兄弟结点
int present, non_present; //present表示此人到场的最大价值, non_present表示此人不到场的最大价值
void init()
{
child=father=brother=non_present=0; //初始化
}
}p[N];
void dfs(int x)
{
int k=p[x].child;
while(k)
{
dfs(k); //深搜下去到子节点,从下到上
p[x].present+=p[k].non_present; //状态转移方程,x到场的话则加上它的孩子不到场的价值
p[x].non_present+=max(p[k].present, p[k].non_present);//x不到场的话则加上他的孩子(到场或不到场---孩子和brother之间也不受影响)的最大值
k=p[k].brother; //x的孩子还包括(x的孩子的brother)
}
return ;
}
int main()
{
int n, t, l, k;
while(scanf("%d", &n)!=EOF)
{
for(t=1; t<=n; ++t)
{
scanf("%d", &p[t].present);
p[t].init();
}
while(scanf("%d%d", &l, &k)!=EOF&&l+k!=0)
{
p[l].father=k;
p[l].brother=p[k].child; //一个接一个,记录上一个
p[k].child=l; //可以从这里逐渐往上推,推出k所有的child
}
for(t=1; t<=n; ++t)
{
if(!p[t].father) //从根节点出发
{
dfs(t); //搜索并记录下来
printf("%d\n", max(p[t].present, p[t].non_present));
break;
}
}
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <map>
#define LL long long
#define inf 0x7fffffff
#define N 250
using namespace std; //hdu2412 树形dp及最佳方案是否唯一
int dp[N][2], dup[N][2]; //dp[n][m]中m为0表示不来,m为1表示来, dup[n][m]表示最佳的方案是不是唯一的,dup[n][m]中m为0表示不唯一,m为1表示唯一
map<string, int> s;
/*
题意:n个人形成一个关系树,每个节点代表一个人,节点的根表示这个人的唯一的直接上司,只有根没有上司。
要求选取一部分人出来,使得每2个人之间不能有直接的上下级的关系,求最多能选多少个人出来,并且求出获得最大人数的选人方案是否唯一。
思路:树形dp
dp[x][0]+=max(dp[k][0], dp[k][1]); k是x的孩子
dp[x][1]+=dp[k][0];
*/
struct node
{
int pre, brother, son;
void init()
{
pre=brother=son=0;
return ;
}
}p[N];
void dfs(int x)
{
int k=p[x].son;
dup[x][0]=dup[x][1]=1; //注意初始化每个人来和不来都是唯一的方案
while(k)
{
dfs(k);
dp[x][0]+=max(dp[k][0], dp[k][1]);
dp[x][1]+=dp[k][0];
if((dp[k][0]>dp[k][1]&&!dup[k][0])||(dp[k][0]<dp[k][1]&&!dup[k][1])||dp[k][0]==dp[k][1])
dup[x][0]=0;
if(!dup[k][0])
dup[x][1]=0;
k=p[k].brother;
}
return ;
}
int main()
{
int n, t, j, k, id1, id2;
string s1, s2;
while(scanf("%d", &n)&&n)
{
s.clear();
memset(dp, 0, sizeof(dp));
for(t=1; t<=n; ++t)
{
p[t].init();
dp[t][1]=1;
}
k=1;
cin>>s1;
s[s1]=k++;
for(t=1; t<n; ++t)
{
cin>>s1>>s2;
if(!s[s1])
{
s[s1]=k++;
}
if(!s[s2])
{
s[s2]=k++;
}
id1=s[s1];
id2=s[s2];
p[id1].pre=id2;
p[id1].brother=p[id2].son;
p[id2].son=id1;
}
dfs(1);
int ans, flag=0;
if(dp[1][0]>dp[1][1])
{
ans=dp[1][0];
if(dup[1][0]==1)
flag=1;
}
else if(dp[1][0]<dp[1][1])
{
ans=dp[1][1];
if(dup[1][1]==1)
flag=1;
}
else
{
ans=dp[1][0];
}
printf("%d ", ans);
if(flag)
{
printf("Yes\n");
}
else printf("No\n");
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <map>
#define LL long long
#define inf 0x7fffffff
#define N 2500
using namespace std; //hdu1054 树形dp
int dp[N][2];
struct node
{
int pre, brother, son;
void init()
{
pre=brother=son=0;
return ;
}
}p[N];
void dfs(int x)
{
int k=p[x].son;
while(k)
{
dfs(k);
dp[x][0]+=dp[k][1];
dp[x][1]+=min(dp[k][0], dp[k][1]);
k=p[k].brother;
}
return ;
}
int main()
{
int n, t, a, k, b;
while(scanf("%d", &n)!=EOF)
{
memset(dp, 0, sizeof(dp));
for(t=1; t<=n; ++t)
{
p[t].init();
dp[t][1]=1;
}
for(t=0; t<n; ++t)
{
scanf("%d:(%d)", &a, &k); //注意这里编号可以从0开始,所以每一个编号都要加1
a++;
while(k--)
{
scanf("%d", &b);
b++;
p[b].pre=a;
p[b].brother=p[a].son;
p[a].son=b;
}
}
int ans;
for(t=1; t<=n; ++t)
{
if(!p[t].pre)
{
dfs(t);
ans=min(dp[t][0], dp[t][1]);
break;
}
}
printf("%d\n", ans);
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <map>
#define LL long long
#define inf 0x7fffffff
#define N 10100
using namespace std; //hdu 2196 树形dp
int vis[N], pre[N], dp[N][3]; //dp[n][m]中n是节点编号, m为0表示从下到上节点的最大值, m为1表示从小到上第2大值, m为2表示从上到下的最大值
/*
题意:给你一棵树,求树上各个节点到其他节点的距离中的最大值
思路:先用邻接表建树,树形dp
*/
struct node
{
int v, next, w; //表示的是一条边
}p[N<<1];
void init()
{
memset(pre, -1, sizeof(pre));
memset(dp, 0, sizeof(dp));
memset(vis, 0, sizeof(vis));
}
void dfs1(int x) //从下到上
{
vis[x]=1;
int j, t, biggest, bigger;
biggest=bigger=0;
for(j=pre[x]; j!=-1; j=p[j].next)
{
if(vis[p[j].v]) //之前访问过的祖先
continue;
dfs1(p[j].v);
if(dp[p[j].v][0]+p[j].w>biggest)
{
bigger=biggest;
biggest=dp[p[j].v][0]+p[j].w;
}
else if(dp[p[j].v][0]+p[j].w>bigger)
{
bigger=dp[p[j].v][0]+p[j].w;
}
dp[x][0]=biggest;
dp[x][1]=bigger;
}
return ;
}
void dfs2(int x) //从上到下
{
vis[x]=1;
int t, j, son;
for(j=pre[x]; j!=-1; j=p[j].next)
{
son=p[j].v;
if(vis[son])continue;
dp[son][2]=(dp[son][0]+p[j].w==dp[x][0]?dp[x][1]:dp[x][0])+p[j].w; //表示这个节点的父亲节点下的其他分支的最大值
dp[son][2]=max(dp[son][2], dp[x][2]+p[j].w); //父亲节点之上的最大值
dfs2(p[j].v);
}
}
int main()
{
int n, t, j, k, a, b;
while(~scanf("%d", &n))
{
k=0;
init();
for(t=2; t<=n; ++t)
{
scanf("%d%d", &a, &b); //无向图
p[k].v=t;
p[k].w=b;
p[k].next=pre[a];
pre[a]=k++;
p[k].v=a;
p[k].w=b;
p[k].next=pre[t];
pre[t]=k++;
}
dfs1(1); //从下到上递推,求出dp[N][0]和dp[N][1]
memset(vis, 0, sizeof(vis));
dfs2(1); //从上到下
for(t=1; t<=n; ++t)
printf("%d\n", max(dp[t][0], dp[t][2]));
}
return 0;
}