Alice和Bob的国家 | ||||||
| ||||||
Description | ||||||
Alice和Bob想去一起占领国家,这个国家有n个城市,为了去占据城市i,Alice需要花费A[i]分钟占领它, Bob需要花费B[i]分钟占领它。由于城市之间有相连关系,如果城市i和城市j是邻城。如果Alice已经占据了 城市i,那么Alice去占据城市j的时间就是A[j]/2。如果j和z也是邻城那么Alice去占据z的时间也是A[z]/2。 对于Bob是同样的。我们定义占据一个国家的时间就是指将这个国家的所有城市占领。现在我们想知道Alice 和Bob一起将这个国家占领所需要的最少时间。(如果一个国家被Alice就不需要被Bob占领了)。 题目保证一个城市到另一个城市有且只有一条道路。 | ||||||
Input | ||||||
第一行是一个整数T代表测试数据组数 对于每组测试数据第一行是一个整数N(0<N<100)代表城市数量,第二行是N个整数代表A[1],A[2]...A[N]。 第三行是N个整数代表B[1],B[2]....B[N]。接下来N-1行,每行两个整数x,y(代表x和y相连)。 | ||||||
Output | ||||||
对于每组测试数据,输出占领一个国家的最少时间。 | ||||||
Sample Input | ||||||
1 3 1 2 5 3 8 1 1 2 1 3 | ||||||
Sample Output | ||||||
3 | ||||||
Author | ||||||
陈禹@HRBUST |
思路(思路及代码参考自:http://blog.csdn.net/lvshubao1314/article/details/43529927):
求最优解,而且是在一棵树上,那么考虑树型Dp.
我们设定Dp【i】【2】【2】:
①Dp【i】【0】【0】:表示到点i,以点i为子树的根这个点是被A攻占并且其子树中不存在攻占起点(全价花费点)的最优解。
②Dp【i】【0】【1】:表示到点i,以点i为子树的根这个点是被A攻占并且其子树中存在攻占起点(全价花费点)的最优解。
③Dp【i】【1】【0】:表示到点i,以点i为子树的根这个点是被B攻占并且其子树中不存在攻占起点(全价花费点)的最优解。
④Dp【i】【1】【1】:表示到点i,以点i为子树的根这个点是被B攻占并且其子树中存在攻占起点(全价花费点)的最优解。
那么状态转移方程:
Dp【u】【0】【0】=a【u】/2+Σmin(Dp【v】【0】【0】,Dp【v】【1】【1】);
这里设定x1=Σmin(Dp【v】【0】【0】,Dp【v】【1】【1】);
Dp【u】【0】【1】有两种情况,一种是当前点u是全价花费点,或者是其子树的某一个点:
Dp【u】【0】【1】=Min(a【u】+x1,a【u】/2+x1+y1);
这里y1就是Dp【v】【0】【1】与min(Dp【v】【0】【0】,Dp【v】【1】【1】)的差值的最小值。
即y1=Min(dp【v】【0】【1】-min(Dp【v】【0】【0】,Dp【v】【1】【1】));
其实每一个差值都是一个半价点变成全价点的花费。这里取最小即最优。
另外Dp【u】【1】【0】和Dp【u】【1】【1】与上述同理。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
vector<int>mp[150];
int a[150];
int b[150];
int dp[150][2][2];
void Dfs(int u,int from)
{
int flag=0;
int x1=0,x2=0;
int y1=0x3f3f3f3f,y2=0x3f3f3f3f;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(v==from)continue;
Dfs(v,u);
flag=1;
x1+=min(dp[v][0][0],dp[v][1][1]);
x2+=min(dp[v][1][0],dp[v][0][1]);
y1=min(y1,dp[v][0][1]-min(dp[v][0][0],dp[v][1][1]));
y2=min(y2,dp[v][1][1]-min(dp[v][1][0],dp[v][0][1]));
}
if(flag==0)
{
dp[u][0][0]=a[u]/2;
dp[u][0][1]=a[u];
dp[u][1][0]=b[u]/2;
dp[u][1][1]=b[u];
return;
}
dp[u][0][0]=a[u]/2+x1;
dp[u][0][1]=min(a[u]+x1,a[u]/2+x1+y1);
dp[u][1][0]=b[u]/2+x2;
dp[u][1][1]=min(b[u]+x2,b[u]/2+x2+y2);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)scanf("%d",&b[i]);
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
Dfs(1,-1);
printf("%d\n",min(dp[1][0][1],dp[1][1][1]));
}
}