第1行 n,表示树中结点的数目。
第2行至第n+1行,每行描述每个通道端点的信息,依次为:该结点标号i(0<i<=n),在该结点安置保安所需的经费k(<=10000),该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,...,rm。
对于一个n(0 < n <= 1500)个结点的树,结点标号在1到n之间,且标号不重复。
五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序。
已知整个地下超市的所有通道呈一棵树的形状;某些通道之间可以互相望见。总经理要求所有通道的每个端点(树的顶点)都要有人全天候看守,在不同的通道端点安排保安所需的费用不同。
一个保安一旦站在某个通道的其中一个端点,那么他除了能看守住他所站的那个端点,也能看到这个通道的另一个端点,所以一个保安可能同时能看守住多个端点(树的结点),因此没有必要在每个通道的端点都安排保安。
请你帮助超市经理策划安排,在能看守全部通道端点的前提下,使得花费的经费最少。
Input
第1行 n,表示树中结点的数目。
第2行至第n+1行,每行描述每个通道端点的信息,依次为:该结点标号i(0<i<=n),在该结点安置保安所需的经费k(<=10000),该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,...,rm。
对于一个n(0 < n <= 1500)个结点的树,结点标号在1到n之间,且标号不重复。
Output
最少的经费。
Sample Input
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
Sample Output
25
下面是我的代码,不知道为何WA 已经n++次了QAQ。。。就是找不出错误在哪里,。。第一次做树形dp,受打击呀。。。。希望各路前辈或者知道的人帮帮忙。到了这个地步感觉调试只能是浪费时间。。
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN = 1510;
int n;
int f[MAXN][2];
int vis[MAXN][MAXN];
int v0[MAXN];
int w[10010],a[10010],temp=0;
void dfs(int u){
v0[u] = true;
for(int i=1; i<=n;i++)
{
if(!vis[u][i])
{continue;}
if(v0[i])
{continue;}
dfs(i);
f[u][0]+=f[i][1];
f[u][1]+=min(f[i][1],f[i][0]);
}
}
int main(){
scanf("%d", &n);
int x,v,u;
memset(vis, 0, sizeof(vis));
memset(v0,0,sizeof(v));
for(int i=1; i<=n; i++){
scanf("%d%d%d", &a[i],&w[i],&x);
while(x--){
scanf("%d", &v);
vis[a[i]][v]=1;vis[v][a[i]]=1;
}
}
for(int i=0; i<=n; i++)
{f[i][1] = w[i]; f[i][0] = 0; }
if(n==1)
{printf("%d\n",w[n]);return 0;}
else dfs(1);
printf("%d\n", min(f[1][0], f[1][1]));
return 0;
}
有点复杂。
http://xcacm.hfut.edu.cn/oj/problem.php?id=1046
可以帮忙看看吗?告诉我哪里错了,还是思路就是不对的就好
@尽善尽美#:
我运行你的代码,结果是25,有什么问题吗?
@519740105: 那个,我自己想的数据测试也是正确的。。但是提交就wa了。所以不明白现在
@尽善尽美#: 不明白你的意思,你的代码我也没细看,只是把代码弄到系统后,是能得到25的。
根据图,25的结果有两个方案:全叶子(4人)和234,其实也有最优的选择需求,具体怎么样就看你了。
我没对你的代码研究,vis怎么用的也不明白,只是模拟你的输入初始化数组的,下面是我的实验代码:
#include "stdafx.h" #include "MGPath.h" #include<cstdio> #include<vector> #include<cstring> using namespace std; const int MAXN = 1510; int n; int f[MAXN][2]; int vis[MAXN][MAXN]; int v0[MAXN]; int w[10010],a[10010],temp=0; void dfs(int u){ v0[u] = true; for(int i=1; i<=n;i++) { if(!vis[u][i]) {continue;} if(v0[i]) {continue;} dfs(i); f[u][0]+=f[i][1]; f[u][1]+=min(f[i][1],f[i][0]); } } void init() { n = 6; a[1] = 1; w[1] = 30; vis[a[1]][2] = 1; vis[2][a[1]] = 1; vis[a[1]][3] = 1; vis[3][a[1]] = 1; vis[a[1]][4] = 1; vis[4][a[0]] = 1; a[2] = 2; w[2] =16; vis[a[2]][5] = 1; vis[5][a[2]] = 1; vis[a[2]][6] = 1; vis[6][a[2]] = 1; a[3] = 3; w[3] = 5; a[4] = 4; w[4] = 4; a[5] = 5; w[5] = 11; a[6] = 6; w[6] = 5; } void run(){ init(); //scanf("%d", &n); //int x,v,u; //memset(vis, 0, sizeof(vis)); //memset(v0,0,sizeof(v)); //for(int i=1; i<=n; i++){ // scanf("%d%d%d", &a[i],&w[i],&x); // while(x--){ // scanf("%d", &v); // vis[a[i]][v]=1;vis[v][a[i]]=1; // } //} for(int i=0; i<=n; i++) {f[i][1] = w[i]; f[i][0] = 0; } if(n==1) {printf("%d\n",w[n]);return;} else dfs(1); printf("%d\n", min(f[1][0], f[1][1])); }
@519740105: vis就是邻接矩阵用来存树的,标记为1的就是两个节点间相连。25的最优方案确实是2 3 4点,这个是肯定的。这个就是部分数据正确不能代表所有的数据都对,只是我现在还没能发现错误的那些数据,所以不知从何下手去改了QAQ,谢谢你耐心的回答
@尽善尽美#: 3456的结果也是25
@519740105: 恐怕你没理解题目意思,3456 并没有覆盖所有的边
@尽善尽美#: 对。我只简单的看所有节点了。
@519740105: 完了 我自己弄吧,多谢你
给个链接啊
http://xcacm.hfut.edu.cn/oj/problem.php?id=1046
谢谢你了,