一些专题上的题目总结

Posted pandaking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些专题上的题目总结相关的知识,希望对你有一定的参考价值。

感觉其实cf c,d级别的树形dp其实没有那么的复杂,主要是要搞清楚一点,怎么利用子树去更新父节点,然后就还是想清楚问题和状态呀!

codeforces682c

题意:在一棵树上存在这样一个种节点   u 。满足u存在v的子树中,(u,v)的之间的边权和大于a[u]的话,那么u点是不开心的。你只能从叶子节点开始删除点,问你最少删除多少个点,可以使得这个树里面没有不开心的点。

 首先这道题目是从根节点出发,然后u,v的边权和大于a[u],那么u是不开心,就要去掉,我们可以保存一个变量,存到纬度里面去,保存从根节点到u上这条链上边权和最大的值,如果大于,则这颗子树都不要了,否则就返回已经在子树中计算的答案。

就是dfs即可

代码:

技术图片
 1 #include <algorithm>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cmath>
 6 #include <vector>
 7 #include <bitset>
 8 typedef long long ll;
 9 using namespace std;
10 const int maxn=100100;
11 int n;
12 ll ai[maxn];
13 int size[maxn];
14 struct node{
15     int to;
16     ll ci;
17     node(int a,ll b):to(a),ci(b){};
18 };
19 vector<node> G[maxn];
20 
21 void dfs1(int u,int fa){
22     size[u]=1;
23     for(int i=0;i<G[u].size();i++){
24         int v=G[u][i].to;
25         if(v==fa) continue;
26         dfs1(v,u);
27         size[u]+=size[v];
28     }
29 }
30 
31 int dfs2(int u,int fa,ll sum){
32     int ans=0;
33     for(int i=0;i<G[u].size();i++){
34         int v=G[u][i].to;
35         ll w=G[u][i].ci;
36         if(v==fa) continue;
37         ans+=dfs2(v,u,max(sum+w,w));
38     }
39     if(sum>ai[u]) return size[u];
40     else return ans;
41 }
42 
43 int main(){
44     while(scanf("%d",&n)!=EOF){
45         for(int i=1;i<=n;i++)  scanf("%lld",&ai[i]);
46         for(int i=2;i<=n;i++){
47             int a;
48             ll b;
49             scanf("%d%lld",&a,&b);
50             G[a].push_back(node(i,b));
51             G[i].push_back(node(a,b));
52         }
53         dfs1(1,-1);
54         printf("%d
",dfs2(1,-1,0));
55     }
56     return 0;
57 }
View Code

 

poj-2152 这道题可以说是一道好题了。

题目大意:有N座城市,要求在这N座城市中建一个消防系统,使得每座城市城市着火时都能被按时扑灭 

现在给出每座城市建一个消防站所需的花费w和每座城市相邻消防站的最远距离lim(和该城市距离超过lim的城市的消防站无法救该城市的火),问要使所有的城市都能被救到火,建消防站的最小花费是多少

首先我们可以这样设置状态,考虑某个节点,假如这个节点能被消火,那么有这几种可能,1是这个消防站建立在这个城市,2是建立在这个城市的子节点,3是建立在这个城市的父节点。

那么不妨可以这样设置状态,设置dp[u][i] 为以节点u为根节点的子树然后第i个城市控制u节点的最小花费。

那么dp[u][i]肯定是要从各个子树上面获取信息的。这样的话我们可以保存一个cost[v],表示子树的最优选择,但是存在一中情况,子树也可以被i所覆盖,那么这样就会导致重复计算,那么这样的话我们就可以这样变一下,取min(cost[v],dp[v][i]-ai[i])+ai[i],这样就可以排除子树会被城市i所控制的情况

这样通过不断统计子树的信息最后便可以解决整个题目。

下面是代码:

技术图片
 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <bitset>
 6 #include <vector>
 7 #include <cmath>
 8 typedef long long ll;
 9 using namespace std;
10 const int maxn=1100;
11 int t,n;
12 struct node{
13      int to,w;
14      node(int a,int b):to(a),w(b){};
15 };
16 int w[maxn],d[maxn],dis[maxn],cost[maxn],dp[maxn][maxn];
17 vector<node> G[maxn];
18 
19 void Dfs(int u,int fa){
20     for(int i=0;i<G[u].size();i++){
21         int v=G[u][i].to;
22         int l=G[u][i].w;
23         if(v==fa) continue;
24         dis[v]=dis[u]+l;
25         Dfs(v,u);
26     }
27 }
28 
29 void dfs(int u,int fa){
30     for(int i=0;i<G[u].size();i++){
31         int v=G[u][i].to;
32         if(v==fa) continue;
33         dfs(v,u);
34     }
35     dis[u]=0;
36     Dfs(u,-1);
37     for(int i=1;i<=n;i++){
38         if(dis[i]<=d[u]){
39             dp[u][i]=w[i];
40             for(int j=0;j<G[u].size();j++){
41                 int v=G[u][j].to;
42                 if(v==fa) continue;
43                 dp[u][i]+=min(cost[v],dp[v][i]-w[i]);
44             }
45             cost[u]=min(cost[u],dp[u][i]);
46         }
47     }
48 }
49 
50 int main(){
51     scanf("%d",&t);
52     while(t--){
53         scanf("%d",&n);
54         for(int i=1;i<=n;i++) scanf("%d",&w[i]);
55         for(int i=1;i<=n;i++) scanf("%d",&d[i]);
56         for(int i=1;i<=n;i++) G[i].clear();
57         for(int i=1;i<n;i++){
58             int u,v,l;
59             scanf("%d%d%d",&u,&v,&l);
60             G[u].push_back(node(v,l));
61             G[v].push_back(node(u,l));
62         }
63         memset(dp,0x3f,sizeof(dp));
64         memset(cost,0x3f,sizeof(cost));
65         dfs(1,-1);
66         printf("%d
",cost[1]);
67     }
68     return 0;
69 }
View Code

ps:(其实没有这么难想,感觉只要第一纬是设以u为根的子树,那么自然而然的就想到了,怎么控制这颗子树了。。。。。。。。。。。。。。。。。

 

以上是关于一些专题上的题目总结的主要内容,如果未能解决你的问题,请参考以下文章

大一下学期以来做题总结

背包真假专题

矩阵乘法加速图上问题专题总结

专题四-图论总结

专题四-图论总结

最小生成树专题