两只蚁队要占领一个山丘,给出两个蚁队占领山丘中每个洞穴所用的时间,若两洞穴相邻,占领其中一个后另一个的时间变成原来的一半,求最少所用时间。
树状动态规划。
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<vector>
using namespace std;
vector<int>g[101];
int t[101][2];
int f[101][2][2];
int v[101];
int min(int x,int y)
{
if(x<y)return x;
return y;
}
void update(int &x,int y)
{
if(x>y)x=y;
}
void dfs(int r,int fa)
{
v[r]=fa;
for(int i=0;i<g[r].size();i++)
if(!v[g[r][i]])
{
dfs(g[r][i],r);
}
for(int a=0;a<2;a++)
{
f[r][a][0]=t[r][a]/2;
int b=1-a;
int change=t[r][a]-t[r][a]/2;
for(int i=0;i<g[r].size();i++)
if(v[g[r][i]]==r)
{
int s=g[r][i];
f[r][a][0]+=min(f[s][a][0],f[s][b][1]);
update(change,f[s][a][1]-min(f[s][a][0],f[s][b][1]));
}
f[r][a][1]=f[r][a][0]+change;
}
}
void read_data(int N)
{
for(int i=1;i<=N;i++)cin>>t[i][0];
for(int i=1;i<=N;i++)cin>>t[i][1];
for(int i=1;i<=N;i++)
{
g[i].clear();
v[i]=0;
}
int x,y;
for(int i=1;i<N;i++)
{
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
}
int main()
{
int N;
while(cin>>N)
{
read_data(N);
dfs(1,-1);
cout<<min(f[1][0][1],f[1][1][1])<<endl;
}
return 0;
}
from sysuoj