赞
踩
Bob喜欢玩电脑游戏,特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。
他要建立一个古城堡,城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵,使得这些士兵能了望到所有的路。
注意,某个士兵在一个结点上时,与该结点相连的所有边将都可以被了望到。
请你编一程序,给定一树,帮Bob计算出他需要放置最少的士兵.
第一行 N,表示树中结点的数目。
第二行至第N+1行,每行描述每个结点信息,依次为:该结点标号i,k(后面有k条边与结点I相连)。
接下来k个数,分别是每条边的另一个结点标号r1,r2,…,rk。
对于一个n(0<n<=1500)个结点的树,结点标号在0到n-1之间,在输入数据中每条边只出现一次。
输出文件仅包含一个数,为所求的最少的士兵数目。
- 4
- 0 1 1
- 1 2 2 3
- 2 0
- 3 0
Copy
1
Copy
Hint 答案为1(只要一个士兵在结点1上)。
可以先看看详解洛谷P1352 没有上司的舞会(树形DP经典例题)-CSDN博客
定义状态dp[x][0/1]表示x这个节点不放/放士兵
根据题意,如果当前节点不放置士兵,那么它的子节点必须全部放置士兵,因为要满足士兵可以看到所有的边
dp[x][0] += dp[son][1]
其中son是u的子节点
如果当前节点放置士兵,只要将dp[x][1]加上它的子节点选不选的最小值就行了(因为树形dp自下而上,上面的节点不需要考虑)
dp[x][1]+=min(dp[son][0],dp[son][1])
- #include <bits/stdc++.h>
- #define int long long
- using namespace std;
- int n,u,v,dp[10001][2];
- vector<int> vec[100001];
- void dfs(int fa,int x)
- {
- dp[x][1] = 1;
- for(int i = 0;i < vec[x].size();i++)
- if(vec[x][i] != fa)
- {
- dfs(x,vec[x][i]);
- dp[x][0] += dp[vec[x][i]][1];
- dp[x][1] += min(dp[vec[x][i]][0],dp[vec[x][i]][1]);
- }
- }
- signed main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)
- {
- int p;
- cin>>p>>u;
- for(int j = 1;j <= u;j++)
- {
- cin>>v;
- vec[p].push_back(v);
- vec[v].push_back(p);
- }
- }
- dfs(-1,0);
- cout<<min(dp[0][1],dp[0][0]);
- return 0;
- }
可以按照反方向的深度优先遍历序列来进行贪心。每检查一个结点,如果当前点和当前点的父节点都不属于顶点覆盖集合,则将父节点加入到顶点覆盖集合,并标记当前节点和其父节点都被覆盖.
虽然说着思路很简单,但是代码细节蛮多的,可以参考一下。
- #include <bits/stdc++.h>
- #define int long long
- using namespace std;
- int n,u,v,ans,fat[100001],cnt;
- struct st
- {
- int zhi,id;
- }dp[100001];
- bool vis[100001];
- vector<int> vec[100001];
- void dfs(int fa,int x,int dep)
- {
- dp[++cnt] = {dep,x};
- fat[x] = fa;
- for(int i = 0;i < vec[x].size();i++)
- if(vec[x][i] != fa)
- dfs(x,vec[x][i],dep + 1);
- }
- bool cmp(st x,st y)
- {
- return x.zhi > y.zhi;
- }
- signed main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)
- {
- int p;
- cin>>p>>u;
- for(int j = 1;j <= u;j++)
- {
- cin>>v;
- vec[p].push_back(v);
- vec[v].push_back(p);
- }
- }
- vis[1501] = 1;
- dfs(1501,0,1);
- sort(dp + 1,1 + dp + n,cmp);
- for(int i = 1;i <= n;i++)
- if(vis[dp[i].id] == 0 && vis[fat[dp[i].id]] == 0)
- {
- vis[fat[dp[i].id]] = 1;
- vis[dp[i].id] = 1;
- ans++;
- }
- cout<<ans;
- return 0;
- }
如果这篇博客对您有帮助的话,请点赞收藏关注支持一下呗!(o゜▽゜)o☆
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。