寒假Day10:树形dp+二分图匹配(匈牙利算法)练习

树形dp

dp[N][2]:

//dp针对当前节点 选或者不选
//dp[i][0];//不选
//dp[i][1];//选

状态转移方程(是关键):

for(int i=0;i<v[root].size();i++)
{
  dp[root][0]+=dp[v[root][i]][1];//若当前节点不选,则子节点必须选
  dp[root][1]+=min(dp[v[root][i]][1],dp[v[root][i]][0]);//当前节点选,子节点(选/不选)
}
 1 //给出n个节点 节点编号0~n-1
 2 //每个节点站一个哨兵,每个哨兵观察到与自己相邻的两条边
 3 //问最少需要多少个哨兵才能观察到所有边
 4 
 5 #include<string.h>
 6 #include<iostream>
 7 #include<stdio.h>
 8 #include<algorithm>
 9 #include<queue>
10 #include<vector>
11 #include<map>
12 #include<cmath>
13 using namespace std;
14 #define inf 0x3f3f3f3f
15 #define inff 0x3f3f3f3f3f3f3f3f
16 const int N=1550;
17 #define mod 998244353
18 typedef long long ll;
19 
20 int n;
21 vector<int>v[N];
22 int f[N],dp[N][2];
23 //dp针对当前节点 选或者不选
24 //dp[i][0];//不选
25 //dp[i][1];//
26 void dfs(int root)
27 {
28     dp[root][0]=0;//当前根节点不选
29     dp[root][1]=1;//当前根节点选
30     for(int i=0;i<v[root].size();i++)
31         dfs(v[root][i]);
32     for(int i=0;i<v[root].size();i++)
33     {
34         dp[root][0]+=dp[v[root][i]][1];//若当前节点不选,则子节点必须选
35         dp[root][1]+=min(dp[v[root][i]][1],dp[v[root][i]][0]);//当前节点选,子节点(选/不选)
36     }
37 }
38 
39 int main()
40 {
41     while(~scanf("%d",&n))
42     {
43         memset(f,-1,sizeof(f));//因为节点编号0~n-1
44         for(int i=1;i<=n;i++)
45         {
46             int root,node,son;
47             scanf("%d:(%d)",&root,&node);
48             v[root].clear();//记得清空
49             for(int j=1;j<=node;j++)
50             {
51                 scanf("%d",&son);
52                 v[root].push_back(son);//单向边
53                 f[son]=root;
54             }
55         }
56         int x=0;
57         while(f[x]!=-1)
58             x=f[x];//找到整棵树的根节点
59         dfs(x);
60         int minn=min(dp[x][0],dp[x][1]);
61         printf("%d\n",minn);
62     }
63     return 0;
64 }
View Code

二分图匹配(匈牙利算法)练习

猜你喜欢

转载自www.cnblogs.com/OFSHK/p/12231729.html
今日推荐