树形DP 或 最小顶点覆盖=最大匹配(双向图)(HDU 1053)
来源:互联网 发布:如何做淘宝客推广 编辑:程序博客网 时间:2024/05/13 05:16
Strategic Game
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5170 Accepted Submission(s): 2377
Problem Description
Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad. Now he has the following problem. He must defend a medieval city, the roads of which form a tree. He has to put the minimum number of soldiers on the nodes so that they can observe all the edges. Can you help him?
Your program should find the minimum number of soldiers that Bob has to put for a given tree.
The input file contains several data sets in text format. Each data set represents a tree with the following description:
the number of nodes
the description of each node in the following format
node_identifier:(number_of_roads) node_identifier1 node_identifier2 ... node_identifier
or
node_identifier:(0)
The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500). Every edge appears only once in the input data.
For example for the tree:
the solution is one soldier ( at the node 1).
The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following table:
Sample Input
4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)
Sample Output
1
2
这道题有两种解题方法:
第一种方法是树形DP:
对于每一个节点,节点的yes表示该节点存在士兵,如果为no的话该节点则不存在士兵,用深搜然后进行回朔,如果某个节点的父节点存在士兵,则该节点可能有士兵或者没有士兵,如果某个节点的父节点不存在士兵的话,那么子节点一定存在士兵。
代码:
#include<stdio.h>#define M 1505struct node{int child[M];int len;int yes,no;};int n,root,a,b,c;node nd[M];int min(int a, int b){return a<b?a:b;}void dfs(int r){nd[r].yes = 1;nd[r].no = 0;for(int i=0;i<nd[r].len;i++){dfs(nd[r].child[i]);nd[r].yes += min(nd[nd[r].child[i]].yes, nd[nd[r].child[i]].no);nd[r].no += nd[nd[r].child[i]].yes;}}int main(){while(scanf("%d", &n)!=EOF){for(int i=0;i<n;i++){scanf("%d:(%d)", &a,&b);if(i==0)root = a;nd[a].len = b;for(int j=0;j<b;j++){scanf("%d",&c);nd[a].child[j] = c;}}dfs(root);printf("%d\n", min(nd[root].yes, nd[root].no));}return 0;}
第二种方法为最小顶点覆盖==最大匹配(双向图)
二分图中,选取最少的点数,使这些点和所有的边都有关联(把所有的边的覆盖),叫做最小点覆盖。
证明最大匹配==最小顶点覆盖
已知某个双向图是最大匹配,所以再也找不到增广路,假设所有的匹配边为n条,那么左右各有n个匹配的点。
标记所有左边匹配边的顶点,则有n个。问题就是证明n=最小点覆盖,即证明最大匹配数n到底能不能覆盖所有的边入手。
对于剩下的未匹配的边,每条边的右边点和左边点,假设左边点不属于上述所说的n个左边,那么就新增了一条增广路(想想增广路的定义就知道了,右未匹配,左未匹配的话那就可以找到增广路了)所以左边点也在匹配边之中,。所以就证明了剩下的未匹配边关联的范围也在这左边的n个匹配点的范围内力了。
代码:
#include<stdio.h>#include<string.h>#include<vector>#include<iostream>using namespace std;#define M 1505int n,a,b,c;vector<int> f[M];int used[M],link[M];int dfs(int a){for(int i=0;i<(int)f[a].size();i++){int j = f[a][i];if(used[j]==0){used[j] = 1;if(link[j]==-1 || dfs(link[j])){link[j] = a;return 1;}}}return 0;}int maxmatch(){int ans = 0;memset(link, -1, sizeof(link));for(int i=0;i<n;i++){memset(used, 0, sizeof(used));ans += dfs(i);}return ans;}int main(){while(scanf("%d", &n)!=EOF){for(int i=0;i<n;i++){f[i].clear();}for(int j=0;j<n;j++){scanf("%d:(%d)", &a, &b);for(int i=0;i<b;i++){scanf("%d", &c);f[a].push_back(c);f[c].push_back(a);} }printf("%d\n", maxmatch()/2);}return 0;}
- 树形DP 或 最小顶点覆盖=最大匹配(双向图)(HDU 1053)
- HDU 1054 最小顶点覆盖 (树形dp)
- HDU 2063 过山车(匈牙利算法 二分图的最小顶点覆盖 二分图最大匹配)
- HDU 4160 Dolls (最小路径覆盖=顶点数-最大匹配数)
- HDU 1151 Air Raid(最小路径覆盖 = 顶点数 - 最大匹配数)
- poj 1325 Machine Schedule(最小顶点覆盖+最大匹配)
- HDU 1150 Machine Schedule(匈牙利算法 二分图的最小顶点覆盖 二分图最大匹配)
- HDU 3729 I'm Telling the Truth (最小路径覆盖=顶点数-最大匹配数)
- 最大匹配、最小顶点覆盖、最大独立集、最小路径覆盖(转)
- hdu 1150 Machine Schedule 最小顶点覆盖(最大匹配)
- hdu 3360 National Treasures 最小顶点覆盖(最大匹配)
- HDU 4160 最小路径覆盖 = 顶点数 - 最大匹配数 二分匹配
- poj3020_最小覆盖路径(顶点个数-二分图最大匹配数)
- POJ3692——Kindergarten (二分图求最小顶点覆盖 (即最大匹配))
- HDU ACM 1054 Strategic Game 二分图最小顶点覆盖?树形DP
- 二分图:最大独立集&最大匹配&最小顶点覆盖
- 【二分图匹配(最小顶点覆盖)】hdu 1150 Machine Schedule(外:hdu 1054 Strategic Game)
- HDU-1150(求最小覆盖顶点数=二分最大匹配数)
- Google式用户体验的十大内在原则
- [UI]Android列表ListView使用
- 【数位DP】 codeforces 55D && FZU chriswho
- AE中出现无法嵌入互操作类型错误
- C# Basic
- 树形DP 或 最小顶点覆盖=最大匹配(双向图)(HDU 1053)
- 判断一个字符串的所有字符是否都在另一个字符串中
- Python flask web框架学习
- 第12周项目4-银行系统-任务1-框架
- Reverse Integer
- 【DirecX 教程】Lesson 6:理解图形概念
- STARTUPINFO 结构初始化 学习笔记
- ZOJ 3802 Easy 2048 Again(压缩dp)
- 《Git Pro 2》学习笔记_Chapter 10_Object Storage