设计状态:
f[u][0]表示u不去舞会,其子树的累加和的最大值
f[u][1]表示u去舞会,其直系下属不去舞会,但已下属为根节点的子树的快乐指数需要累加
#include
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e6+7;
const int inf=1e18;
const int mod=19980829;
int n,a[N],din[N],f[N][2];
vector<int>e[N];
void dfs(int u,int pre)
{
f[u][1]=a[u];
for(int v:e[u])
{
if(v==pre) continue;
dfs(v,u);
f[u][1]+=f[v][0];
f[u][0]+=max(f[v][1],f[v][0]);
}
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<n;i++)
{
int u,v;cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
din[u]++;
}
int g;
for(int i=1;i<=n;i++)
if(!din[i]) g=i;
dfs(g,0);
cout<<max(f[g][0],f[g][1])<<endl;
}
signed main()
{
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
}
//#include
#include
#include
#include
#include
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e6+7;
const int inf=1e18;
const int mod=19980829;
int n,cnt,head[N],dp[N][3],p[N];
struct node
{
int to,nxt,w;
}e[N];
void add(int from,int to,int w)
{
e[++cnt].to=to;
e[cnt].w=w;
e[cnt].nxt=head[from];
head[from]=cnt;
}
void dfs1(int u,int pre)
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==pre) continue;
dfs1(v,u);
if(dp[v][0]+e[i].w>dp[u][0])
{
dp[u][1]=dp[u][0];
dp[u][0]=dp[v][0]+e[i].w;
p[u]=v;
}
else if(dp[v][0]+e[i].w>dp[u][1])
dp[u][1]=dp[v][0]+e[i].w;
}
}
void dfs2(int u,int pre)
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==pre) continue;
if(v==p[u])
dp[v][2]=e[i].w+max(dp[u][1],dp[u][2]);
else
dp[v][2]=e[i].w+max(dp[u][0],dp[u][2]);
dfs2(v,u);
}
}
void solve()
{
while(cin>>n)
{
cnt=0;
for(int i=0;i<=n;i++)
head[i]=dp[i][0]=dp[i][1]=dp[i][2]=p[i]=0;
for(int i=2;i<=n;i++)
{
int v,w;cin>>v>>w;
add(i,v,w),add(v,i,w);
}
dfs1(1,0);
dfs2(1,0);
for(int i=1;i<=n;i++)
cout<<max(dp[i][0],dp[i][2])<<endl;
}
}
signed main()
{
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
}
#include
#include
#include
#include
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=2e6+7;
const int inf=1e18;
const int mod=19980829;
int ans,cnt,head[N],d[N];
bool vis[N];
struct node
{
int to,nxt,w;
}e[N];
void add(int from,int to,int w)
{
e[++cnt].to=to;
e[cnt].w=w;
e[cnt].nxt=head[from];
head[from]=cnt;
}
int dfs1(int u)
{
d[u]=0;
vis[u]=1;
int d1=0,d2=0;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(vis[v]) continue;
dfs1(v);
if(d[v]+e[i].w>=d1)
d2=d1,d1=d[v]+e[i].w;
else if(d[v]+e[i].w>d2)
d2=d[v]+e[i].w;
}
d[u]=d1;
return d1+d2;
}
void solve()
{
int u,v,w;
while(scanf("%d%d%d", &u, &v, &w) == 3)
{
add(u,v,w),add(v,u,w);
}
ans=dfs1(1);
printf("%d\n", ans);
}
signed main()
{
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
}
思路是正解,但总是报运行错误,找了半个多小时,索性不找了,可能是码分问题,也不常在这个oj上做题。
问题找到了,在poj上用define int long long
要小心!!!
该问题的本质是求解最少边覆盖。若该点放置士兵,则子结点应选择代价较少的士兵数;若改点不放置士兵,则其子节点必须放置士兵。
#include
#include
#include
#include
//#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=3005;
const int inf=1e18;
const int mod=19980829;
int n,cnt,head[N],dp[N][2],din[N];
bool vis[N];
struct node
{
int to,nxt;
}e[N];
void add(int from,int to)
{
e[++cnt].to=to;
//e[cnt].w=w;
e[cnt].nxt=head[from];
head[from]=cnt;
}
void dfs(int u,int pre)
{
vis[u]=1;
dp[u][1]=1;
for(int i=head[u];~i;i=e[i].nxt)
{
int v=e[i].to;
if(v==pre||vis[v]) continue;
dfs(v,u);
dp[u][1]+=min(dp[v][0],dp[v][1]);
dp[u][0]+=dp[v][1];
}
}
void solve()
{
while(~scanf("%d",&n))
{
cnt=0;
for(int i=0;i<=n;i++)
head[i]=-1,dp[i][0]=dp[i][1]=vis[i]=0;
for(int i=1;i<=n;i++)
{
int u,v,d;scanf("%d:(%d)",&u,&d);
for(int j=1;j<=d;j++)
{
cin>>v;
add(u,v);add(v,u);
}
}
dfs(0,-1);
printf("%d\n",min(dp[0][0],dp[0][1]));
}
}
signed main()
{
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
}
小工具:可用lowerbound处理每个点所在左右边界的关系
#include
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=5e5+5;;
const int inf=1e18;
const int mod=19980829;
int n,d,g,a[N];
struct node
{
int x,h;
bool operator <(const node &a){
return x<a.x;
}
}e[N];
struct n1
{
int l,r;
}c[N];
//ST表
int lg[N]; //记录log2N的整数值
int st[N][30]; //以i为左端点长度为2的j次方的序列所求最值
void ST(int n)
{
lg[1]=0;
for(int i=2;i<=n;i++)
lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
for(int i=1;i<=n;i++)
st[i][0]=e[i].h;
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
}
}
int sch(int l,int r)
{
if(l>r)
return 0;
int k=lg[r-l+1];
return max(st[l][k],st[r-(1<<k)+1][k]);
}
void solve()
{
cin>>n>>d;
for(int i=1;i<=n;i++)
cin>>e[i].x>>e[i].h;
sort(e+1,e+n+1);
for(int i=1;i<=n;i++)
{
int d1=e[i].x-d,d2=e[i].x+d;
int pos1=lower_bound(e+1,e+n+1,node{d1,e[i].h})-e;
int pos2=lower_bound(e+1,e+n+1,node{d2,e[i].h})-e;
if(e[pos2].x>d2) pos2--;
if(pos2>n) pos2--;
//cout<
c[++g].l=pos1,c[g].r=pos2;
}
ST(n);
int ans=0;
for(int i=1;i<=n;i++)
{
int mx1=sch(c[i].l,i),mx2=sch(i,c[i].r);
//cout<
if(mx1>=e[i].h*2&&mx2>=e[i].h*2)
ans++;
}
cout<<ans<<endl;
}
signed main()
{
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
}