poj3342
最近做树形dp,渣渣被虐成喳喳喳辣,真是不开森。。。。
还是适合做基础入门题。。。╮(╯▽╰)╭
题意:比较好理解。就是一棵树,选m个点,儿子和父亲不能同时选。问最多能选多少个(题目中说的是上级,当然我这里省略就是用父亲节点和孩子结点表示啦~~)
其实dp的内容很好想,d[i][0]表示第i个点不选的结果,d[i][1]表示第i个点选的结果,转移方程d[i][0]=sigma(max(d[j][0],d[j][1])) ,就是儿子可选可不选,选出最大的就ok
d[i][1]=sigma(d[j][0]) 父亲选了,当然儿子就不能选。
主要问题是建图,我可能还是不太会,因为这里用的map和vector 。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<map>
using namespace std;
#define maxn 220
vector<int>edge[maxn]; //记录边的信息 edge[i][j]表示以i为起点的第j条边的终点的序列号
int d[maxn][2];
void dfs(int u)
{
d[u][0]=0;d[u][1]=1;
for(int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
dfs(v);
d[u][0]+=max(d[v][0],d[v][1]);
d[u][1]+=d[v][0];
}
}
int main()
{
//freopen("q.in","r",stdin);
int i,j,n,tot;//tot记录节点数
map<string,int> mp;
char bos[110],a[110],b[110];
while(~scanf("%d",&n) && n)
{
tot=0;
for(i=0;i<maxn;i++)edge[i].clear();
mp.clear();
memset(d,0,sizeof(d));
scanf("%s",bos);
mp[bos]=tot++;
for(i=1;i<n;i++)
{
scanf("%s%s",a,b);
if(mp.find(a)==mp.end())mp[a]=tot++;
if(mp.find(b)==mp.end())mp[b]=tot++;
edge[mp[b]].push_back(mp[a]); //形成一条边
}
dfs(0);
bool flag;
for(i=0;i<n;i++)
{
flag=true;
if(d[i][0]>d[i][1])
{
for(j=0;j<edge[i].size();j++)
{
if(d[edge[i][j]][0]==d[edge[i][j]][1])
{
flag=false;
break;
}
}
}
if(!flag)break;
}
cout<<max(d[0][0],d[0][1])<<" ";
if(d[0][0]==d[0][1] || !flag)cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
}
poj2342
做完上一题,做这个他觉得思路更清晰了,不过还是错了一点,就是这个题的根节点没有直接给出,还要自己找。我刚开始是觉得根节点不会出现在孩子学列的那一排,也就是程序中的所有的a,然后把所有的a保存起来,拍一下序,看缺谁,谁就是根节点。但是WA。。。
后来看了别人的方法,是孩子父亲保存在一起,一起找,另开了个数组,然后才A的。。。。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define maxn 6002
vector<int> edge[maxn];
int d[maxn][2];
int w[maxn];
int fa[maxn];
void dfs(int u)
{
int i,j;
d[u][0]=0;d[u][1]=w[u];
for(i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
dfs(v);
d[u][0]+=max(d[v][0],d[v][1]);
d[u][1]+=d[v][0];
}
}
int main()
{
// freopen("q.in","r",stdin);
int n,i,j;
int sta=0;
int a,b;
memset(d,0,sizeof(d));
memset(w,0,sizeof(w));
memset(fa,0,sizeof(fa));
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&w[i]);
while(scanf("%d%d",&a,&b)==2 && a+b)
{
fa[a]=b;
edge[b].push_back(a); //还需要找到根节点 根节点肯定不会出现在孩子的序列当中
}
for(i=1;i<=n;i++)if(!fa[i]){sta=i;break;} //根节点刚开始出了点问题。。。。贡献了WA....
// cout<<sta<<endl;
dfs(sta);
int ans=max(d[sta][0],d[sta][1]);
if(ans<0)cout<<ans<<endl;
else cout<<ans<<endl;
}